在 JavaScript 中下载 PDF blob 时出现问题

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52817280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 10:01:37  来源:igfitidea点击:

Problem downloading a PDF blob in JavaScript

javascriptfiledownloadbase64blob

提问by Barry Michael Doyle

I've created a function that takes a bloband fileNamewhich is supposed to download that blob implemented as follows:

我创建了一个函数,它需要一个blobfileName应该下载该 blob 实现如下:

const blobToBase64 = (blob, callback) => {
  const reader = new FileReader();
  reader.onloadend = () => {
    const base64 = reader.result;
    console.log({ base64 });
    callback(base64);
  };
  reader.readAsDataURL(blob);
};

const downloadFile = (blob, fileName) => () => {
  const link = document.createElement('a');
  blobToBase64(blob, (base64) => {
    link.href = base64;
    link.download = fileName;
    link.click();
  });
};


downloadFile(myBlob, myFileName);

To try debug this I've made a console.logto log out the value of base64which is created by reader.result.

为了尝试调试这个,我已经console.log注销了base64reader.result.

That base64value is data:application/octet-stream;base64,Mzc4MDY4...

base64值是data:application/octet-stream;base64,Mzc4MDY4...

My PDF file get's downloaded but it's corrupted. What am I doing wrong in my file download implementation?

我的 PDF 文件已下载,但已损坏。我在文件下载实现中做错了什么?

Let me know if there are any additional details that might help with this? I'm 100% sure that the blob itself is not a corrupted file.

让我知道是否有任何其他细节可能对此有所帮助?我 100% 确定 blob 本身不是损坏的文件。

回答by Kaiido

I can't tell for sure why your code doesn't work, but I can tell for sure that what you are doing is useless at best.

我无法确定为什么您的代码不起作用,但我可以确定您所做的充其量是无用的。

Do not convert a Blob to a dataURI, 99%* of the time, what you want to do with this dataURI can be done directly with the original Blob and a blobURI.

不要将 Blob 转换为 dataURI,99%* 的情况下,您想对这个 dataURI 做什么可以直接使用原始 Blob 和 blobURI 来完成。

*The remaining 1% being when you need to create standalone documents that will include binary data, it happens but not that often.

*剩下的 1% 是当您需要创建包含二进制数据的独立文档时,这种情况会发生,但并不经常发生。

Here, once again what you want to do (set an anchor to point to your Blob's data) can be done with the Blob directly: simply create a blobURI (which is just a pointer to the data in memory) by calling URL.createObjectURL(blob).

在这里,您想要做的事情(设置一个指向 Blob 数据的锚点)可以直接使用 Blob 完成:只需通过调用URL.createObjectURL(blob).

const downloadFile = (blob, fileName) => {
  const link = document.createElement('a');
  // create a blobURI pointing to our Blob
  link.href = URL.createObjectURL(blob);
  link.download = fileName;
  // some browser needs the anchor to be in the doc
  document.body.append(link);
  link.click();
  link.remove();
  // in case the Blob uses a lot of memory
  window.addEventListener('focus', e=>URL.revokeObjectURL(link.href), {once:true});
};


downloadFile(new Blob(['random data']), "myfile.txt");

回答by Akansh

I tried using Fetch API to download the PDF file from server which is giving octet-streamcontent as response. So, if you check the response, you will get characters like these %PDF-1.4

我尝试使用 Fetch API 从提供octet-stream内容作为响应的服务器下载 PDF 文件。所以,如果你检查响应,你会得到这样的字符%PDF-1.4

Here is the solution:

这是解决方案:

function download(pdfUrl) {
        fetch(pdfUrl).then(resp => resp.arrayBuffer()).then(resp => {

            // set the blog type to final pdf
            const file = new Blob([resp], {type: 'application/pdf'});

            // process to auto download it
            const fileURL = URL.createObjectURL(file);
            const link = document.createElement('a');
            link.href = fileURL;
            link.download = "FileName" + new Date() + ".pdf";
            link.click();
        });
    }

You can use the same method and decode the content of the octet-stream before creating the blob.

您可以使用相同的方法并在创建 blob 之前解码八位字节流的内容。