使用javascript下载时PDF为空白
Posted
技术标签:
【中文标题】使用javascript下载时PDF为空白【英文标题】:PDF is blank when downloading using javascript 【发布时间】:2016-03-29 21:58:06 【问题描述】:我有一个 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 输出流的 PDF 字节数组。而且流也没有加密。
因此,当我单击该链接时,会成功下载一个大小约为 200KB 的 PDF 文件。但是当我打开这个文件时,它会打开空白页。下载的pdf文件的起始内容在图片中。
我不明白这里有什么问题。救命!
这是下载的pdf文件开始内容:
【问题讨论】:
您使用的媒体类型为 "text/pdf";这是自找麻烦,pdf不是文本格式,是二进制,把它当成文本可以毁掉它。请改用 application/pdf。 @mkl 将其更改为 application /pdf 但问题仍然相同。 这里使用 text/pdf 仍然是错误的。此外,您的屏幕截图看起来确实像某些代码将文件视为文本,使用单字节编码(Latin1)读取并使用 UTF-8 写入。 这可能会对您有所帮助:***.com/a/31763030/5042982。在 AngularJS 中添加responseType :blob
对我有用。
【参考方案1】:
感谢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)
)
【讨论】:
【参考方案2】:我在我的 React 项目中遇到了同样的问题。 在 API 上,我使用 express 的 res.download() 将 PDF 文件附加到响应中。通过这样做,我收到了一个基于字符串的文件。这就是文件打开空白或损坏的真正原因。
在我的情况下,解决方案是强制 responseType 为“blob”。由于我是通过 axios 发出请求的,所以我只是简单地将这个 attr 添加到选项对象中:
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);
【讨论】:
【参考方案3】:我从服务器获取数据作为字符串(这是 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)上测试它并没有工作。 谢谢!使用 createObjectURL 帮助解决了我遇到的网络错误,但我的 PDF 无法打开,但您的解决方案可以正常工作。 截至 2018 年,使用 chrome / windows 10 可以正常工作。 太棒了!谢谢:)【参考方案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();
【讨论】:
感谢@Alexey,我遇到了同样的问题,使用 angularjs 我不得不将 responseType = 'arraybuffer' 放到 感谢@Alexey,我在 React 和 typescript 中尝试使用 axios 时遇到了同样的问题。我通过一些修改实现了上述解决方案,并使用 1.1MB 文件作为下载文件,以及 iframe 中的 PDF 视图。 这适用于现代库和获取,例如axiosresponseType: 'blob'
是必须的
我只能使用 responseType: 'arraybuffer'
和 axios 让它工作。我最初尝试使用responseType: 'blob'
,然后使用Buffer.from(exampleBlob,'binary')
转换为数组缓冲区,但无论出于何种原因导致pdf文件损坏/格式不正确以上是关于使用javascript下载时PDF为空白的主要内容,如果未能解决你的问题,请参考以下文章
我正在尝试将 pdf 文件从节点服务器下载到反应客户端,但是当我打开它时,它显示为空白
使用 FileProvider uri 打开 PDF 文件会打开一个空白屏幕