如何从内容处置中获取文件名

IT技术 javascript ajax filenames file-type content-disposition
2021-02-17 06:41:48

我下载了一个文件作为 ajax 的响应。如何从中获取文件名和文件类型content-disposition并为其显示缩略图。我得到了很多搜索结果,但找不到正确的方法。

$(".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);     
    }
});

控制台输出:

inline; filename=demo3.png
6个回答

这是我以前使用它的方式。我假设您将附件作为服务器响应提供。

我从我的 REST 服务中设置了这样的响应头 response.setHeader("Content-Disposition", "attachment;filename=XYZ.csv");

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, '');
        }
    }
}

更多在这里

我简直不敢相信 JavaScript 有时是多么愚蠢和丑陋......
2021-04-21 06:41:48
我认为最好使用disposition.startsWith("attachment")而不是disposition.indexOf('attachment') !== -1,因为文件名可能包含附件
2021-04-22 06:41:48
要匹配这样的 utf8 模式:dis = "attachment; filename*=UTF-8''filename.pdf"尝试/filename\*?=([^']*'')?([^;]*)/.exec(dis)[2]
2021-05-02 06:41:48
此解决方案不适用于以下情况:附件;文件名*=UTF-8''文件名.txt使用此正则表达式,文件名将是UTF-8filename.txt
2021-05-12 06:41:48
filename = matches[1].replace(/['"]/g, '');什么?
2021-05-17 06:41:48

这是对 marjon4 答案的改进。

选择答案的一种更简单的方法是使用 split ;

var fileName = xhr.getResponseHeader('content-disposition').split('filename=')[1].split(';')[0];

注意:如果您的文件名本身包含分号 (;),则此解决方案可能无法按预期工作

当文件名本身包含filename=.
2021-04-21 06:41:48
该解决方案适用于filename*=UTF-8' '格式 您可能指的整个格式是这样的content-disposition: "attachment; filename=document.pdf; filename*=UTF-8''document.pdf"请尝试理解并回答,然后再说它不起作用!是的,对于所有技术问题,如果文件名本身包含分号,则此解决方案将不起作用。但在大多数情况下,文件名不包含分号,因此考虑到这个借口,它对我来说效果很好!(仍在我的回答中为此添加注释。)
2021-04-22 06:41:48
如果文件名作为分号,这不会失败吗?
2021-05-02 06:41:48
这是一种幼稚的方法,不推荐。如果文件名包含分号,这可能会返回不正确的结果。缺少对filename*=UTF-8''.
2021-05-03 06:41:48

或者干脆只是:

var fileName = xhr.getResponseHeader('Content-Disposition').split("filename=")[1];
不适用于以下格式: content-disposition: "attachment; filename=document.pdf; filename*=UTF-8''document.pdf"
2021-04-26 06:41:48
添加了解决@AlexM 提到的问题的答案
2021-05-17 06:41:48

在我的情况下,标题如下所示:

attachment; filename="test-file3.txt"

因此,我能够使用命名组正则表达式很容易地提取文件名:

const regExpFilename = /filename="(?<filename>.*)"/;

const filename: string | null = regExpFilename.exec(contentDispositionHeader)?.groups?.filename ?? null;

我知道我在这里有点偏离主题,因为 OP 没有在文件名周围加上引号,但仍然共享以防有人遇到与我刚刚做的相同的模式

如果你想获取文件名并支持那些奇怪的 url 编码的 UTF-8 头和 ascii 头,你可以使用这样的东西

public getFileName(disposition: string): string {
    const utf8FilenameRegex = /filename\*=UTF-8''([\w%\-\.]+)(?:; ?|$)/i;
    const asciiFilenameRegex = /filename=(["']?)(.*?[^\\])\1(?:; ?|$)/i;

    let fileName: string = null;
    if (utf8FilenameRegex.test(disposition)) {
      fileName = decodeURIComponent(utf8FilenameRegex.exec(disposition)[1]);
    } else {
      const matches = asciiFilenameRegex.exec(disposition);
      if (matches != null && matches[2]) {
        fileName = matches[2];
      }
    }
    return fileName;
}

一些注意事项:

  1. 这将采用 UTF-8 文件名的值(如果已设置)覆盖 ascii 名称
  2. 下载时,您的浏览器可能会进一步更改名称以替换某些字符,例如", 与_(Chrome)
  3. ascii 模式最适用于带引号的文件名,但支持不带引号的值。在这种情况下,它将标题值filename=的下一个;或末尾之后和之前的所有文本视为文件名。

MDN 内容处置标头

@MoonStom 这是一个好点,我会更新。
2021-04-19 06:41:48
这是一个很好的答案,我只需要进行一个更改并添加i到第一个正则表达式的末尾,因为我的标头返回为filename*=utf-8not UTF-8
2021-04-29 06:41:48
ASCII 文件名不必用单引号或双引号括起来。
2021-05-01 06:41:48