ChatGPT解决这个技术问题 Extra ChatGPT

没有链接的 JavaScript blob 文件名

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

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 。


k
kol

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

创建一个隐藏的 标签。将其 href 属性设置为 blob 的 URL。将其下载属性设置为文件名。单击 标记。

这是一个简化的示例 (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 中尝试过)
N
N8allan

我只是想通过支持 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 中有效。谢谢。
K
Kim Nyholm

与上述解决方案的原理相同。但是我遇到了 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)”对我有用
M
Martin Schmelzer

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

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

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

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

函数 export2json() { 常量数据 = { 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("下载", "data.json"); document.body.appendChild(a); a.点击(); document.body.removeChild(a); }


W
WSBT

下载按钮的工作示例,将来自 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();
}

做得好,谢谢帮助!
S
Sacky San

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

s
segu

这是一个很好的简单解决方案。

function downloadBloob(blob,FileName) {
    var link = document.createElement("a"); // Or maybe get it from the current document
    link.href = blob;
    link.download = FileName;
    link.click();
}

您的答案可以通过额外的支持信息得到改进。请编辑以添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。您可以在 help center 中找到有关如何写出好的答案的更多信息。
R
Rey0bs

如果您想下载 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');