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

时间:2016-12-02 19:11:29

标签: javascript ajax filenames file-type content-disposition

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

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

9 个答案:

答案 0 :(得分:50)

这是我在某个时候使用它的方式。 我假设您提供附件作为服务器响应。

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

More here

答案 1 :(得分:11)

或者只是:

var fileName = xhr.getResponseHeader('Content-Disposition').split("filename=")[1];

答案 2 :(得分:8)

这是对marjon4答案的改进。

一种简化选择答案的方法是使用像这样的拆分;

```{r setup}
knitr::opts_knit$set(root.dir = 'C:/the-desired-path')

```

答案 3 :(得分:3)

尝试以下解决方案:

var header = xhr.getResponseHeader('Content-Disposition');
var startIndex = header.indexOf("filename=") + 10; // Adjust '+ 10' if filename is not the right one.
var endIndex = contentDisposition.length - 1; //Check if '- 1' is necessary
var filename = contentDisposition.substring(startIndex, endIndex);
console.log("filename: " + filename)

答案 4 :(得分:2)

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

attachment; filename="test-file3.txt"

因此,我能够使用命名组regexp轻松提取文件名:

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

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

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

答案 5 :(得分:1)

有一个可以执行此任务的npm软件包:content-disposition

答案 6 :(得分:0)

如果您不使用多部分正文,那么您可以使用此功能。它从 Content-Disposition 标头值(字符串如:inline; filename=demo3.png)中提取文件名并根据需要进行解码。

const getFileNameFromContentDisposition = disposition => { 
    if (disposition
        && (disposition.startsWith('attachment') || disposition.startsWith('inline'))
    ) {
        let filename = disposition.startsWith('attachment')
            ? disposition.replace("attachment;", "")
            : disposition.replace("inline;", ""); //replaces first match only
        filename = filename.trim();
        if (filename.startsWith("filename=")) {
            filename = filename.replace("filename=", "")
                .slice(1, filename.length - 1); //remove quotes
        } else if (filename.startsWith("filename*=")) {
            filename = filename.replace("filename*=", "")
                .split("''").slice(1).join("''"); //remove encoding and ''
            filename = decodeURIComponent(filename);
        }
        return filename;
    }
}

函数的结果可以拆分为name和extension如下:

let name = getFileNameFromContentDisposition("inline; filename=demo.3.png").split(".");
let extension = name[name.length - 1];
name = name.slice(0, name.length - 1).join(".");
console.log(name); // demo.3
console.log(extension); //png

您可以显示缩略图,例如,使用 svg:

let colors = {"png": "red", "jpg": "orange"};
//this is a simple example, you can make something more beautiful
let createSVGThumbnail = extension => `<svg xmlns="http://www.w3.org/2000/svg" width="18" height="20" viewBox="0 0 18 20">
    <rect x="0" y="0" width="18" height="20" fill = "#FAFEFF"/>
    <rect x="0" y="7" width="18" height="6" stroke="${colors[extension] || "blue"}" fill = "${colors[extension] || "blue"}"/>
    <text stroke = "white" fill = "white" font-size = "6" x = "0" y = "12.5" textLength = "18">${extension.toUpperCase()}</text>
</svg>`;

...

//You can use it as HTML element background-image
let background = "data:image/svg+xml;base64," + btoa(new TextDecoder().decode(createSVGThumbnail("png"))); 

答案 7 :(得分:0)

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

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

    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)

答案 8 :(得分:-2)

在我的情况下没有在stackoverflow上找到任何响应。我收到了类似的内容处理:内联;文件名* = UTF-8''Dossier%20de%20diagnostic%20technique.pdf

我修改了正则表达式来处理UTF-8字符串(如果存在): var regex = / filename [^; = \ n] =(UTF-8(['“] ))?(。*)/;

这是我的功能:

function getFileNameByContentDisposition(contentDisposition){
    var regex = /filename[^;=\n]*=(UTF-8(['"]*))?(.*)/;
    var matches = regex.exec(contentDisposition);
    var filename;

    if (matches != null && matches[3]) { 
      filename = matches[3].replace(/['"]/g, '');
    }

    return decodeURI(filename);
}
编辑:我没有那么多测试。不要忘记在NodeJS代码中使用try / catch包装它。