使用javascript下载时PDF为空白

IT技术 javascript pdf
2021-03-20 20:49:10

我有一个 Web 服务,它在其响应中返回 PDF 文件内容。当用户单击链接时,我想将其下载为 pdf 文件。我在UI中编写的javascript代码如下:

$http.get('http://MyPdfFileAPIstreamURl').then(function(response){
var blob=new File([response],'myBill.pdf',{type: "text/pdf"});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download="myBill.pdf";
link.click();
});

“响应”包含来自“MyPdfFileAPIstreamURl”的 servlet 输出流的 PDF 字节数组。而且流也没有加密。

因此,当我单击该链接时,会成功下载一个大小约为 200KB 的 PDF 文件。但是当我打开这个文件时,它打开了空白页。下载的pdf文件的起始内容在图片中。

我不明白这里有什么问题。帮助 !

这是下载的pdf文件起始内容:

这是下载的pdf文件起始内容

4个回答

通过 XMLHttpRequest 和xhr.responseType = 'arraybuffer'; 代码解决了它

var xhr = new XMLHttpRequest();
    xhr.open('GET', './api/exportdoc/report_'+id, true);
    xhr.responseType = 'arraybuffer';
    xhr.onload = function(e) {
       if (this.status == 200) {
          var blob=new Blob([this.response], {type:"application/pdf"});
          var link=document.createElement('a');
          link.href=window.URL.createObjectURL(blob);
          link.download="Report_"+new Date()+".pdf";
          link.click();
       }
    };
xhr.send();
这适用于现代图书馆和获取,例如 axiosresponseType: 'blob'是必要的
2021-04-22 20:49:10
谢谢@Alexey,我在 React 和 typescript 中尝试使用 axios 时遇到了同样的问题。我通过一些修改实现了上述解决方案,并使用 1.1MB 文件作为下载,以及 iframe 中的 PDF 视图。
2021-04-26 20:49:10
我只能让它responseType: 'arraybuffer'与 axios一起使用我最初尝试使用responseType: 'blob',然后转换为数组缓冲区,Buffer.from(exampleBlob,'binary')但无论出于何种原因导致损坏/格式不正确的 pdf 文件
2021-05-05 20:49:10
谢谢@Alexey,我遇到了同样的问题,使用 angularjs 我不得不将 responseType = 'arraybuffer' 放入
2021-05-11 20:49:10

我从服务器获取数据作为字符串(它是 base64 编码为字符串),然后在客户端我将其解码为 base64,然后到数组缓冲区。

示例代码

function solution1(base64Data) {

    var arrBuffer = base64ToArrayBuffer(base64Data);

    // It is necessary to create a new blob object with mime-type explicitly set
    // otherwise only Chrome works like it should
    var newBlob = new Blob([arrBuffer], { type: "application/pdf" });

    // IE doesn't allow using a blob object directly as link href
    // instead it is necessary to use msSaveOrOpenBlob
    if (window.navigator && window.navigator.msSaveOrOpenBlob) {
        window.navigator.msSaveOrOpenBlob(newBlob);
        return;
    }

    // For other browsers: 
    // Create a link pointing to the ObjectURL containing the blob.
    var data = window.URL.createObjectURL(newBlob);

    var link = document.createElement('a');
    document.body.appendChild(link); //required in FF, optional for Chrome
    link.href = data;
    link.download = "file.pdf";
    link.click();
    window.URL.revokeObjectURL(data);
    link.remove();
}

function base64ToArrayBuffer(data) {
    var binaryString = window.atob(data);
    var binaryLen = binaryString.length;
    var bytes = new Uint8Array(binaryLen);
    for (var i = 0; i < binaryLen; i++) {
        var ascii = binaryString.charCodeAt(i);
        bytes[i] = ascii;
    }
    return bytes;
};
在桌面和安卓浏览器中工作正常。在 iPhone(safari 和 chrome)上对其进行了测试,但没有奏效。
2021-04-21 20:49:10
惊人的!谢谢 :)
2021-04-29 20:49:10
谢谢!使用 createObjectURL 有助于解决我遇到的网络失败错误,但我的 PDF 无法打开,但您的解决方案使其正常工作。
2021-05-11 20:49:10
截至 2018 年,使用 chrome/windows 10 可以正常工作。
2021-05-14 20:49:10
这个答案帮助了我!谢谢。
2021-05-18 20:49:10

我在 React 项目中遇到了同样的问题。在 API 上,我使用 res.download() 的 express 在响应中附加 PDF 文件。通过这样做,我收到了一个基于字符串的文件。这就是文件打开为空白或损坏的真正原因。

在我的情况下,解决方案是强制 responseType 为“blob”。由于我是通过 axios 发出请求,我只是简单地在选项对象中添加了这个属性:

axios.get('your_api_url_here', { responseType: 'blob' })

之后,要进行下载,您可以在“fetchFile”方法中执行以下操作:

const response = await youtServiceHere.fetchFile(id)
const pdfBlob = new Blob([response.data], { type: "application/pdf" })

const blobUrl = window.URL.createObjectURL(pdfBlob)
const link = document.createElement('a')
      link.href = blobUrl
      link.setAttribute('download', customNameIfYouWantHere)
      link.click();
      link.remove();
URL.revokeObjectURL(blobUrl);

感谢rom5jp解决了这个问题,但添加了 golang 和 nextjs 的示例代码

在 golang 中使用 gingonic 上下文

c.Header("Content-Description", "File-Transfer")
c.Header("Content-Transfer-Encoding", "binary")
c.Header("Content-Disposition","attachement; filename="+fileName)
c.Header("Content-Type",  "application/pdf; charset=utf-8")

c.File(targetPath)
//c.FileAttachment(targetPath,fileName)
os.RemoveAll(targetPath)

在下一个js

  const convertToPDF = (res) => {
  const uuid = generateUUID();

  var a = document.createElement('a');
  var url = window.URL.createObjectURL(new Blob([res],{type: "application/pdf"}));
  a.href = url;
  a.download = 'report.pdf';
  a.click();
  window.URL.revokeObjectURL(url);

}

  const convertFile = async() => {
    axios.post('http://localhost:80/fileconverter/upload', {
      "token_id" : cookies.access_token,
      "request_type" : 1,
      "url" : url
    },{
      responseType: 'blob'
    }).then((res)=>{

     convertToPDF(res.data)

    }, (err) => {
      console.log(err)
    })
  }