使用javascript下载时,PDF为空

使用javascript下载时,PDF为空,javascript,pdf,Javascript,Pdf,我有一个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=wi

我有一个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();
});
“response”包含来自“MyPdfFileAPIstreamURl”的servlet outputstream的PDF字节数组。而且流也没有加密

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

我不明白这里怎么了。救命啊

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


通过XMLHttpRequest和
xhr.responseType='arraybuffer'解决了这个问题
代码:


我从服务器获取数据作为字符串(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;
};
函数解决方案1(base64Data){
var arrBuffer=base64ToArrayBuffer(base64Data);
//有必要创建一个显式设置mime类型的新blob对象
//否则,只有Chrome才能正常工作
var newBlob=newBlob([arrBuffer],{type:“application/pdf”});
//IE不允许将blob对象直接用作链接href
//相反,有必要使用msSaveOrOpenBlob
if(window.navigator&&window.navigator.msSaveOrOpenBlob){
window.navigator.msSaveOrOpenBlob(newBlob);
返回;
}
//对于其他浏览器:
//创建指向包含blob的ObjectURL的链接。
var data=window.URL.createObjectURL(newBlob);
var link=document.createElement('a');
document.body.appendChild(link);//FF中需要,Chrome可选
link.href=数据;
link.download=“file.pdf”;
link.click();
window.URL.revokeObjectURL(数据);
link.remove();
}
函数base64ToArrayBuffer(数据){
var binaryString=window.atob(数据);
var binaryLen=binaryString.length;
var bytes=新的Uint8Array(二进制数);
对于(var i=0;i
我在React项目中也面临同样的问题。 在API上,我使用express的res.download()将PDF文件附加到响应中。通过这样做,我收到了一个基于字符串的文件。这就是文件打开时空白或损坏的真正原因

在我的例子中,解决方案是强制responseType为“blob”。因为我是通过axios发出请求的,所以我只是在option对象中添加了这个属性:

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

您使用的媒体类型为“text/pdf”;这是自找麻烦,pdf不是一种文本格式,它是二进制的,把它当作文本处理会破坏它。请改为使用application/pdf。@mkl将其更改为application/pdf,但问题仍然相同。在此处使用text/pdf仍然是错误的。此外,您的屏幕截图看起来确实像是一行中的某个地方。一些代码将文件视为文本,使用单字节编码(拉丁文1)读取它,然后使用UTF-8写入它。这可能会帮助您:。添加
responseType:blob
在AngularJS中对我很有效。这个答案帮助我找到了伴侣!谢谢。在桌面和安卓浏览器中工作正常。在iPhone(safari和chrome)上进行了测试,但没有成功。谢谢!使用createObjectURL有助于解决我遇到的失败的网络错误,但我的PDF无法打开,但您的解决方案使其正常工作。从2018年开始,使用chrome/windows 10,这一切都如愿以偿。太棒了!谢谢:)谢谢@Alexey,我也遇到了同样的问题,使用angularjs我不得不将responseType='arraybuffer'放在Hanks@Alexey上,我试图在React和typescript中使用axios解决同样的问题。我通过一些修改实现了上述解决方案,并使用1.1MB文件作为下载,以及iframe中的PDF视图。这也适用于现代库和获取,例如,axios
responseType:“blob”
是必需的,我只能使用axios的
responseType:“arraybuffer”
使其工作。我最初尝试使用
responseType:“blob”
,然后用
Buffer.from(例如blob,'binary')
转换为arraybuffer,但由于某种原因导致pdf文件损坏/格式不正确,这让我很高兴,谢谢你,伙计。
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);