Displaying Attachment PDF with Frontend Javascript
背景
笔者最近在参加某校在线平台前端的开发,收到了这样的要求:
将服务器传输过来的文件尽可能(图片/PDF)在网页中就显示下来,这样就不用下载了!
笔者劈里啪啦敲下了如下代码(由于渲染问题,美元符号已替换为人民币符号!!!):
var xhr = new XMLHttpRequest();
¥.ajax({
url: 'download_link',
type: 'get',
data: {},
xhr: function () {
return xhr;
},
success: function (r) {
const params = new URLSearchParams(xhr.responseURL);
const para1 = params.get('filename');
console.log("Returned url:"+xhr.responseURL);
console.log(para1);
if (para1 == null) {
¥('#fast_load').text('');
return;
}
if (para1.endsWith(".png") || para1.endsWith(".jpg") || para1.endsWith(".gif") || para1.endsWith(".bmp")) {
¥('#fast_load').html(`用户上传的图片(为正常显示,已缩放。请点击下载按钮下载原图。)<br/><br/><img src="¥{xhr.responseURL}" style="max-width:600px;width:100%"/>`);
return;
}
if(para1.endsWith(".pdf")){
¥('#fast_load').html(`用户上传的PDF<br/><br/><object class="pdf" data="¥{xhr.responseURL}" width="100%" height="1500"></object>`);
return;
}
¥('#fast_load').text(`用户上传了文件:¥{para1},请按下载按钮下载。请注意:本网站不对用户上传内容进行检查,文件有可能包含恶意内容。`);
}
});
上述代码可以正确分辨并显示各种常用类型的图片文件,然而pdf文件则会直接下载,不会显示在object中,令人迷惑。
问题分析
原来,服务器返回的是Content-Type是application/octet-stream
,而又是以attachment
的形式送给我们的,这时候无论iframe
embed
还是 object
都不会尝试在浏览器中渲染该pdf,而是直接下载。我们无法改变服务器发送的数据类型,于是我们尝试在客户端层面解决问题。
解决思路
用Blob类型接受response然后本地改变Content-Type到application/pdf
,再用本地数据渲染。
问题解决
首先,我们需要以Blob类型处理response,然而据说jquery处理blob类型有许多问题(事实上笔者也确实碰到了问题),所以我们换用普通的Ajax:
var req = new XMLHttpRequest();
req.open("GET", "...", true);
req.responseType = "blob";
req.onload = function (event) {
var blob=req.response;
//...
};
req.send();
接下来,我们发现Blob的类型还是octet-stream
,直接放入object中仍然失败,所以我们需要修改其type
。然而Blob是immutable的,我们无法直接修改其参数。根据本文,我们这么修改blob
的类型:
//hacky solution!!
blob = blob.slice(0, blob.size, "application/pdf")
最后我们使用非常强大的URL工具创建本地URL:
if(para1.endsWith(".pdf")){
blob=blob.slice(0,blob.size,"application/pdf");
const url=URL.createObjectURL(blob);
¥('#fast_load').html(`用户上传的PDF<br/><br/><object class="pdf" data="¥{url}" width="100%" height="1500"></object>`);
return;
}
该URL会随着document卸载而卸载,本场景下不用手动卸载。
(欸,我的代码中的美元都到哪去了?)
重点
- 如何获取服务器上的Blob数据
- 如何修改Blob的类型
- 如何用Blob创建本地URL
版权声明:
作者:XGN
链接:https://blog.hellholestudios.top/archives/1568
来源:Hell Hole Studios Blog
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论