没有链接的JavaScript blob文件名

Ash*_*lue 161 javascript html5 blob download html5-filesystem

当强制通过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);
}
Run Code Online (Sandbox Code Playgroud)

运行上面的代码会立即下载文件而不会刷新页面,如下所示:

bfefe410-8d9c-4883-86c5-d76c50a24a1d

我想将文件名设置为my-download.json.

kol*_*kol 280

我知道的唯一方法是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);
Run Code Online (Sandbox Code Playgroud)

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

笔记

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

  • 这对我不起作用,因为我需要在新选项卡中打开文件.我必须在Chrome中显示PDF,但我需要在URL工具栏中显示用户友好名称,如果用户想通过下载图标下载,我必须在文件中添加相同的用户友好名称. (3认同)
  • @AshBlue"下载"属性需要HTML5.我的代码只是一个示例,您也可以尝试FileSaver.js演示页面:http://eligrey.com/demos/FileSaver.js/ (2认同)
  • 只是想提一下,此解决方案不适用于大小超过特定阈值的文件.例如 - > 2 MB用于镀铬.此大小因浏览器而异. (2认同)
  • 只是补充一下,您不需要实际将 a 标签安装到正文上才能使其工作(刚刚在 Chrome 中尝试过) (2认同)

Ale*_*dru 44

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

这是一个小提琴的例子.天啊.


Kim*_*olm 21

与上述解决方案相同的原理.但我遇到了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)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 我发现这个 setTimeout() hack 修复了 MS Edge,文件根本无法下载。但是,只有对 revokeObjectURL() 的调用需要延迟。 (2认同)

小智 11

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

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢@ben。一切正常。没有dom元素,没有什么像click事件那样触发。只要适当扩展,它就很棒。但是不考虑给定的文件名,而是下载“ &lt;object_url_id&gt; .csv”而不是“ &lt;myfileName&gt; .csv” (2认同)
  • 在`location.assign`之后调用`revokeObjectURL`在Firefox中工作正常,但在Chrome上中断了下载。 (2认同)
  • 正如 @RamBabuS 所说,这并没有保留“fileName”,但除此之外,这对我来说非常有效 (2认同)
  • filename 属性在 firefox 中有效,但在 chrome 中无效...有人有 chrome 的解决方案吗? (2认同)
  • 该文件名在 Chrome 中不起作用,所以不要浪费时间 (2认同)

dab*_*eng 9

这是我的解决方案。从我的角度来看,你无法绕过<a>.

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);
}
Run Code Online (Sandbox Code Playgroud)
<button onclick="export2json()">Export data to json file</button>
Run Code Online (Sandbox Code Playgroud)


小智 6

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)


use*_*613 5

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

HTML:

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

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();
}
Run Code Online (Sandbox Code Playgroud)