Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/367.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从内容处置中获取文件名_Javascript_Ajax_Filenames_File Type_Content Disposition - Fatal编程技术网

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

Javascript 如何从内容处置中获取文件名,javascript,ajax,filenames,file-type,content-disposition,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: "G

作为对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

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

我从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('inline') !== -1) {
        var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
        var matches = filenameRegex.exec(disposition);
        if (matches != null && matches[1]) { 
          filename = matches[1].replace(/['"]/g, '');
        }
    }
}

尝试以下解决方案:

var contentDisposition = xhr.getResponseHeader('Content-Disposition');
var startIndex = contentDisposition.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)

有一个npm包可以完成这项工作:

或者只是:

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

这是对marjon4答案的改进

选择答案的一个非常简单的方法是像这样使用split

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


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

在本例中,标题如下所示:

attachment; filename="test-file3.txt"
因此,我能够使用命名组regexp非常轻松地提取文件名:

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

const filename: string | null = regExpFilename.exec(contentDispositionHeader)?.groups?.filename ?? null;
const regExpFilename=/filename=“(?*”)/;
常量文件名:string | null=regExpFilename.exec(contentDispositionHeader)?.groups?.filename??无效的

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

如果您不使用多部分正文,则可以使用此函数。它从内容处置头值(类似于: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;
    }
}
函数的结果可分为名称和扩展名,如下所示:

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"))); 
let colors={“png”:“red”,“jpg”:“orange”};
//这是一个简单的例子,你可以做一些更漂亮的东西
让createSVGThumbnail=扩展=>`
${extension.toUpperCase()}
`;
...
//您可以将其用作HTML元素背景图像
让background=“data:image/svg+xml;base64”+btoa(新的textdecker().decode(createSVGThumbnail(“png”));

如果您想获取文件名并同时支持怪异的url编码UTF-8和ascii头,您可以使用如下内容

公共getFileName(处置:string):string{ 常量utf8FilenameRegex=/filename\*=UTF-8''([\w%\-\.]+)(?:;|$)/; 常量asciiFilenameRegex=/filename=([“'])(.*?[^\\])\1(?:;|$)/; 让fileName:string=null; if(utf8FilenameRegex.test(处置)){ fileName=decodeURIComponent(utf8FilenameRegex.exec(disposition)[1]); }否则{ const matches=asciiFilenameRegex.exec(处置); if(matches!=null&&matches[2]){ fileName=匹配[2]; } } 返回文件名; }
几点注意:

  • 这将采用UTF-8文件名的值(如果设置)覆盖ascii名称
  • 您的浏览器可能会进一步更改名称,以将某些字符(如
    )替换为
    (Chrome)


  • 控制台怎么说?为什么要设置
    window.location.href=”http://localhost:8080/prj/“+data+”/“+uiid+”/getfile”?这将导致浏览器离开页面并仅显示该URL。如果您已离开页面,您希望如何显示图像的缩略图?为什么需要服务器建议您将文件保存为的文件名以生成缩略图?从内容处置中获取文件名是一个问题。您无法从中获取文件类型,至少不可靠,这就是内容类型头的用途。缩略图显示将来自数据,这是一个完全独立的问题。我需要在缩略图附近显示文件名。但我可以从文件名本身
    filename.jpg
    找到文件类型
    filename=matches[1]。替换(/['']/g'))
    do?此解决方案不适用于以下情况:attachment;filename*=UTF-8''filename.txt。使用此正则表达式,文件名将为UTF-8filename.txt。我无法相信JavaScript有时会多么狡猾和丑陋……也无法与这样的utf8模式匹配:
    dis=“attachment;filename*=UTF-8''filename.pdf“
    试试
    /filename\*?=([^']*”)([^;]*)/.exec(dis)[2]
    我认为最好使用
    disposition.startsWith(“附件”)
    而不是
    disposition.indexOf(“附件”)!==-1
    ,因为文件名可能包含附件,不能使用以下格式:
    内容处置:“附件;filename=document.pdf;文件名*=UTF-8''document.pdf“
    添加了一个解决@AlexMWouldn提到的问题的答案,如果文件名中有分号,这不是失败吗?这是一种幼稚的方法,不推荐使用。如果文件名包含分号,则可能返回不正确的结果。缺少对
    filename*=UTF-8''
    的支持。该解决方案适用于
    filename*=UTF-8''
    格式您可能指的整个格式如下
    内容配置:“附件;filename=document.pdf;filename*=UTF-8''document.pdf”
    。在说这行不通之前,请试着理解并回答!是的,从技术上讲,如果文件名本身有分号,这个解决方案将不起作用。但在大多数情况下,文件名不包含分号,所以在考虑到这个借口的情况下,它对我来说效果很好!(仍然在我的回答中添加了一个注释。)当文件名本身包含
    filename=
    时,它也不适用于en-edge大小写。它似乎在浏览器上不起作用。
    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")));