如何从内容描述中获取文件名
如何从内容描述中获取文件名
我通过ajax下载了一个文件。如何从content-disposition
中获取文件名和文件类型,并显示缩略图。我找到了很多搜索结果,但是找不到正确的方法。\n
$(".download_btn").click(function () { var uiid = $(this).data("id2"); $.ajax({ url: "http://localhost:8080/prj/" + data + "/" + uiid + "/getfile", type: "GET", error: function (jqXHR, textStatus, errorThrown) { console.log(textStatus, errorThrown); }, success: function (response, status, xhr) { var header = xhr.getResponseHeader('Content-Disposition'); console.log(header); } });
\n控制台输出:\ninline; filename=demo3.png\n
问题出现的原因是需要从content-disposition中获取文件名,但是content-disposition的格式有多种可能,包括UTF-8编码和ASCII编码。为了解决这个问题,提供了一个代码示例,可以通过正则表达式从content-disposition中提取文件名。
解决方法如下:
1. 首先定义两个正则表达式,分别用于匹配UTF-8编码和ASCII编码的文件名。其中,UTF-8编码的正则表达式为/filename\*=UTF-8''([\w%\-\.]+)(?:; ?|$)/i
,ASCII编码的正则表达式为/^filename=(["']?)(.*?[^\\])\1(?:; ?|$)/i
。
2. 如果content-disposition中匹配到了UTF-8编码的文件名,则使用decodeURIComponent()
函数对其进行解码,并将解码后的文件名赋值给fileName
变量。
3. 如果content-disposition中没有匹配到UTF-8编码的文件名,则使用ASCII编码的正则表达式进行匹配。为了防止ReDos攻击,先将content-disposition转换为小写,并找到第一个出现filename=
的位置。然后从该位置开始切割字符串,并使用ASCII编码的正则表达式进行匹配。如果匹配成功,并且匹配结果的第二个分组存在,则将其赋值给fileName
变量。
4. 最后,返回文件名fileName
。
需要注意的几点是:
1. 如果content-disposition中同时存在UTF-8编码和ASCII编码的文件名,将使用UTF-8编码的文件名。
2. 下载文件时,浏览器可能会进一步修改文件名,例如将某些字符替换为下划线。
3. ASCII编码的正则表达式适用于带引号的文件名,但也支持不带引号的文件名。在这种情况下,它将filename=
之后,下一个;
或者header值的末尾之前的所有文本作为文件名。
4. 代码示例中没有清理路径信息。如果你正在使用这段代码保存网站上的文件,浏览器会处理这个问题。但如果在Node.js应用程序等环境中使用,务必根据操作系统清理路径信息,只保留文件名,否则可能会使用精心构造的文件名来覆盖系统文件。
在处理content-disposition时,由于其格式的多样性,需要使用正则表达式来提取文件名。通过匹配UTF-8编码和ASCII编码的文件名,可以从content-disposition中获取到正确的文件名。在代码实现时,需要注意一些细节,如优先使用UTF-8编码的文件名、处理特殊字符、防止ReDos攻击等。
问题的原因是在从content-disposition中获取文件名时,存在一些特殊情况没有考虑到,例如文件名中包含分号(;)或者包含特殊字符。这可能导致获取到的文件名不正确。
解决方法是对代码进行改进,使用更加健壮的方法来获取文件名。可以使用正则表达式或者其他字符串处理方法来提取文件名。另外,可以考虑使用现成的库或者工具来处理content-disposition,以确保获取到的文件名是正确的。
以下是对代码的改进示例:
var contentDisposition = xhr.getResponseHeader('content-disposition'); var pattern = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = pattern.exec(contentDisposition); var fileName = matches[1].replace(/['"]/g, '');
这样的改进可以处理更多的情况,包括文件名中包含分号或者特殊字符的情况。通过使用正则表达式匹配文件名,并且去除多余的引号,可以确保获取到的文件名是正确的。
需要注意的是,为了保证代码的健壮性,仍然需要根据具体的情况进行测试和调整。不同的服务器或者文件类型可能会有不同的content-disposition格式,需要适配不同的情况来获取正确的文件名。
总之,通过对代码的改进和使用更加健壮的方法,可以解决从content-disposition中获取文件名的问题,确保获取到的文件名是正确的。这样可以更好地处理文件下载或者其他涉及到文件名的操作。
如何从内容中获取文件名?
有时候我们需要从服务器响应中获取附件的文件名。以下是一个示例:
// 设置响应头 response.setHeader("Content-Disposition", "attachment;filename=XYZ.csv");
在JavaScript中,我们可以通过以下方式获取文件名:
function(response, status, xhr){ var filename = ""; var disposition = xhr.getResponseHeader('Content-Disposition'); if (disposition && disposition.indexOf('attachment') !== -1) { var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) { filename = matches[1].replace(/['"]/g, ''); } } }
如果需要使用`inline`而不是`attachment`,可以使用以下代码:
function(response, status, xhr){ var filename = ""; var disposition = xhr.getResponseHeader('Content-Disposition'); if (disposition && disposition.indexOf('inline') !== -1) { var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) { filename = matches[1].replace(/['"]/g, ''); } } }
这个解决方案无法处理类似于`attachment; filename*=UTF-8''filename.txt`这样的情况。使用这个正则表达式,文件名将变成`UTF-8filename.txt`。为了解决这个问题,可以使用以下正则表达式:
/filename\*?=([^']*'')?([^;]*)/.exec(disposition)[2]
另外,为了更好地匹配UTF-8编码的文件名,可以使用以下正则表达式:
(filename\*=UTF-8''|filename=)(.+\b)
以上是从内容中获取文件名的解决方法。