【问题标题】:JavaScript blob filename without link没有链接的 JavaScript blob 文件名
【发布时间】:2013-10-20 02:25:28
【问题描述】:

通过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

【问题讨论】:

    标签: javascript html download blob html5-filesystem


    【解决方案1】:

    我知道的唯一方法是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 文件对我有用。

    【讨论】:

    • @AshBlue “下载”属性需要 HTML5。我的代码只是一个例子,你也可以试试 FileSaver.js 演示页面:eligrey.com/demos/FileSaver.js
    • 有趣的是,如果您反复尝试以这种方式下载 txt(通过一次又一次按下 jsfiddle.net 上的“运行”按钮),下载有时会失败。
    • 只想提一下,此解决方案不适用于大小超过特定阈值的文件。例如-> 2 MB 用于 chrome。这个大小因浏览器而异。
    • 这对我不起作用,因为我需要在新选项卡中打开文件。我必须在 Chrome 中显示 PDF,但我需要在 URL 工具栏中显示用户友好名称,如果用户想通过下载图标下载,我必须在文件中输入相同的用户友好名称。跨度>
    • 只是补充一下,您不需要将 a 标签实际安装到正文中以使其工作(刚刚在 Chrome 中尝试过)
    【解决方案2】:

    我只是想扩展已接受的答案,支持 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();
    }
    

    Here is an example Fiddle神速

    【讨论】:

    • 完美运行。
    • 我使用了公认的解决方案,但它在 Firefox 中不起作用!我仍然不知道为什么。您的解决方案在 Firefox 中有效。谢谢。
    【解决方案3】:

    与上述解决方案的原理相同。但是我遇到了 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 example

    【讨论】:

    • 我发现这个 setTimeout() hack 修复了 MS Edge,文件根本无法下载。但是,只有对 revokeObjectURL() 的调用需要延迟。
    • 我发现“if (window.navigator.msSaveOrOpenBlob)”对我有用
    【解决方案4】:
    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);
            }
        }
    

    【讨论】:

    • 有什么办法可以在其中打开一个新窗口吗?
    • 我认为您可以调用link.click() 而不是调度鼠标事件。
    【解决方案5】:

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

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

    【讨论】:

    • 谢谢@ben。这工作正常。没有 dom 元素,没有什么能像点击事件那样触发。它只是在适当的扩展下工作得很好。但不考虑给定的文件名,下载“.csv”而不是“.csv”
    • location.assign 之后调用 revokeObjectURL 在 Firefox 中可以正常工作,但在 Chrome 上会中断下载。
    • 请注意“Edge 不支持 File 构造函数。”参考。 caniuse.com/#feat=fileapi
    • 正如@RamBabuS 所说,这不是保留fileName,但除此之外对我来说非常有效
    • filename 属性在 Firefox 中有效,但在 chrome 中无效……任何人有 chrome 的解决方案吗?
    【解决方案6】:

    工作示例下载按钮,将来自 url 的猫照片保存为“cat.jpg”:

    HTML:

    <button onclick="downloadUrl('https://i.imgur.com/AD3MbBi.jpg', 'cat.jpg')">Download</button>
    

    JavaScript:

    function downloadUrl(url, filename) {
      let xhr = new XMLHttpRequest();
      xhr.open("GET", url, true);
      xhr.responseType = "blob";
      xhr.onload = function(e) {
        if (this.status == 200) {
          const blob = this.response;
          const a = document.createElement("a");
          document.body.appendChild(a);
          const blobUrl = window.URL.createObjectURL(blob);
          a.href = blobUrl;
          a.download = filename;
          a.click();
          setTimeout(() => {
            window.URL.revokeObjectURL(blobUrl);
            document.body.removeChild(a);
          }, 0);
        }
      };
      xhr.send();
    }
    

    【讨论】:

      【解决方案7】:

      window.location.assign 对我不起作用。它下载正常,但在 Windows 平台上下载的 CSV 文件没有扩展名。以下对我有用。

          var blob = new Blob([csvString], { type: 'text/csv' });
          //window.location.assign(window.URL.createObjectURL(blob));
          var link = window.document.createElement('a');
          link.href = window.URL.createObjectURL(blob);
          // Construct filename dynamically and set to link.download
          link.download = link.href.split('/').pop() + '.' + extension; 
          document.body.appendChild(link);
          link.click();
          document.body.removeChild(link);
      

      【讨论】:

        【解决方案8】:

        这是我的解决方案。在我看来,你不能绕过&lt;a&gt;

        function export2json() {
          const data = {
            a: '111',
            b: '222',
            c: '333'
          };
          const a = document.createElement("a");
          a.href = URL.createObjectURL(
            new Blob([JSON.stringify(data, null, 2)], {
              type: "application/json"
            })
          );
          a.setAttribute("download", "data.json");
          document.body.appendChild(a);
          a.click();
          document.body.removeChild(a);
        }
        &lt;button onclick="export2json()"&gt;Export data to json file&lt;/button&gt;

        【讨论】:

          【解决方案9】:

          如果您想下载 pdf 并且不强制使用 window.location,您可以使用 jsPdf,如下所示:

          // Create document
          const doc = new jsPDF('l', 'px', 'a4');
          
          // [...] Add here the jsPdf doc filling
          
          // Launch the document downloading
          doc.output('save', 'filename.pdf');
          

          【讨论】:

            猜你喜欢
            • 2017-08-31
            • 2015-12-06
            • 1970-01-01
            • 1970-01-01
            • 2013-08-03
            • 2017-12-15
            • 1970-01-01
            • 1970-01-01
            • 2016-01-22
            相关资源
            最近更新 更多