当前位置: 首页>>技术问答>>正文


强制下载时,如何在JavaScript中设置Blob文件名称?

当强制通过window.location下载时,如何在JavaScript中设置blob文件的名称?

function newFile(data) {
    var json = JSON.stringify(data);
    var blob = new Blob([json], {type: "octet/stream"});
    var url  = window.URL.createObjectURL(blob);
    window.location.assign(url);
}

运行上面的代码会立即下载文件而不会刷新页面,文件名类似如下所示的随机字符串:

bfefe410-8d9c-4883-86c5-d76c50a24a1d

那么我想将文件名设置为my-download.json,该怎么做?

 

最佳解决思路

我知道的唯一方法是FileSaver.js使用的技巧:

  1. 创建隐藏的<a>标记。
  2. 将其href属性设置为blob的URL。
  3. 将其download属性设置为文件名。
  4. 单击<a>标记。

这是一个简化的例子(jsfiddle):

var saveData = (function () {
    var a = document.createElement("a");
    document.body.appendChild(a);
    a.style = "display: none";
    return function (data, fileName) {
        var json = JSON.stringify(data),
            blob = new Blob([json], {type: "octet/stream"}),
            url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
    };
}());

var data = { x: 42, s: "hello, world", d: new Date() },
    fileName = "my-download.json";

saveData(data, fileName);

我写这个例子只是为了说明这个想法,在生产代码中使用FileSaver.js代替。

注意

  • 较旧的浏览器不支持”download”属性,因为它是HTML5的一部分。
  • 浏览器认为某些文件格式不安全,会下载失败。保存带有txt扩展名的JSON文件对我有用。

 

次佳解决思路

我扩展了上文中的答案,可支持Internet Explorer(大多数现代版本),并且使用了jQuery整理代码:

$(document).ready(function() {
    saveFile("Example.txt", "data:attachment/text", "Hello, world.");
});

function saveFile (name, type, data) {
    if (data != null && navigator.msSaveBlob)
        return navigator.msSaveBlob(new Blob([data], { type: type }), name);
    var a = $("<a style='display: none;'/>");
    var url = window.URL.createObjectURL(new Blob([data], {type: type}));
    a.attr("href", url);
    a.attr("download", name);
    $("body").append(a);
    a[0].click();
    window.URL.revokeObjectURL(url);
    a.remove();
}

Fiddle示例

 

第三种解决思路

与上述解决方案相同的原理。但我遇到了Firefox 52.0(32位)的问题,其中大文件(> 40 MBytes)在随机位置被截断。 Re-scheduling调用 revokeObjectUrl()解决了这个问题。

function saveFile(blob, filename) {
  if (window.navigator.msSaveOrOpenBlob) {
    window.navigator.msSaveOrOpenBlob(blob, filename);
  } else {
    const a = document.createElement('a');
    document.body.appendChild(a);
    const url = window.URL.createObjectURL(blob);
    a.href = url;
    a.download = filename;
    a.click();
    setTimeout(() => {
      window.URL.revokeObjectURL(url);
      document.body.removeChild(a);
    }, 0)
  }
}

 

第四种思路

我遇到了同样的问题,我的解决方案。

function newFile(data, fileName) {
    var json = JSON.stringify(data);
    //IE11 support
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        let blob = new Blob([json], {type: "application/json"});
        window.navigator.msSaveOrOpenBlob(blob, fileName);
    } else {// other browsers
        let file = new File([json], fileName, {type: "application/json"});
        let exportUrl = URL.createObjectURL(file);
        window.location.assign(exportUrl);
        URL.revokeObjectURL(exportUrl);
    }
}

 

第五种思路

saveFileOnUserDevice = function(file){ // content: blob, name: string
        if(navigator.msSaveBlob){ // For ie and Edge
            return navigator.msSaveBlob(file.content, file.name);
        }
        else{
            let link = document.createElement('a');
            link.href = window.URL.createObjectURL(file.content);
            link.download = file.name;
            document.body.appendChild(link);
            link.dispatchEvent(new MouseEvent('click', {bubbles: true, cancelable: true, view: window}));
            link.remove();
            window.URL.revokeObjectURL(link.href);
        }
    }

参考资料

 

本文由《纯净天空》出品。文章地址: https://vimsky.com/article/4171.html,未经允许,请勿转载。