没有链接的 JavaScript blob 文件名

IT技术 javascript html download blob html5-filesystem
2021-02-05 14:14:09

强制下载时,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

6个回答

我知道的唯一方法是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 代替。

笔记

  • 较旧的浏览器不支持“下载”属性,因为它是 HTML5 的一部分。
  • 浏览器认为某些文件格式不安全,下载失败。使用 txt 扩展名保存 JSON 文件对我有用。
这对我不起作用,因为我需要在新选项卡中打开文件。我必须在 Chrome 中显示 PDF,但我需要在 URL 工具栏中显示用户友好名称,如果用户想通过下载图标下载,我必须在文件中放置相同的用户友好名称。
2021-03-13 14:14:09
@AshBlue “下载”属性需要 HTML5。我的代码只是一个例子,你也可以试试 FileSaver.js 演示页面:eligrey.com/demos/FileSaver.js
2021-03-20 14:14:09
只是补充一下,您不需要将 a 标签实际安装到正文中才能使其正常工作(刚刚在 Chrome 中尝试)
2021-03-25 14:14:09
只是想提一下,此解决方案不适用于大小大于特定阈值的文件。例如-> 2 MB 用于 chrome。此大小因浏览器而异。
2021-03-26 14:14:09
有趣的是,如果您反复尝试以这种方式下载 txt(通过一次又一次地按 jsfiddle.net 上的“运行”按钮),下载有时会失败。
2021-04-07 14:14:09

我只是想通过支持 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神速

完美地工作。
2021-03-13 14:14:09
我使用了公认的解决方案,但它在 Firefox 中不起作用!我仍然不知道为什么。您的解决方案在 Firefox 中有效。谢谢。
2021-04-05 14:14:09

与上述解决方案的原理相同。但是我在使用 Firefox 52.0(32 位)时遇到了问题,其中大文件(> 40 MB)在随机位置被截断。重新安排 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)
  }
}

jsfiddle 示例

我发现“if (window.navigator.msSaveOrOpenBlob)”对我有用
2021-03-10 14:14:09
我发现这个 setTimeout() hack 修复了 MS Edge,文件根本无法下载。但是,只有对 revokeObjectURL() 的调用需要延迟。
2021-04-05 14:14:09

晚了,但由于我遇到了同样的问题,我添加了我的解决方案:

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);
    }
}
请注意“Edge 不支持 File 构造函数”。参考 caniuse.com/#feat=fileapi
2021-03-14 14:14:09
正如@RamBabuS 所说,这并没有保留fileName,但除此之外,这对我来说非常有效
2021-03-15 14:14:09
filename 属性在 Firefox 中有效,但在 chrome 中无效……有人解决 chrome 吗?
2021-03-19 14:14:09
在 Firefox 中调用revokeObjectURLafterlocation.assign工作正常,但在 Chrome 上会中断下载。
2021-03-22 14:14:09
谢谢@本。这工作正常。没有 dom 元素,没有像点击事件那样触发。它只是在适当的扩展下工作得很棒。但不考虑给定的文件名,下载“<object_url_id>.csv”而不是“<myfileName>.csv”
2021-03-27 14:14:09
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);
        }
    }
有没有办法在其中打开一个新窗口?
2021-03-19 14:14:09
我认为您可以调用link.click()而不是调度鼠标事件。
2021-04-09 14:14:09