背景
笔者最近在参加某校在线平台前端的开发,收到了这样的要求:
将服务器传输过来的文件尽可能(图片/PDF)在网页中就显示下来,这样就不用下载了!
笔者劈里啪啦敲下了如下代码(由于渲染问题,美元符号已替换为人民币符号!!!):
1 | var xhr = new XMLHttpRequest(); |
上述代码可以正确分辨并显示各种常用类型的图片文件,然而pdf文件则会直接下载,不会显示在object中,令人迷惑。
问题分析
原来,服务器返回的是Content-Type是application/octet-stream
,而又是以attachment
的形式送给我们的,这时候无论iframe
embed
还是 object
都不会尝试在浏览器中渲染该pdf,而是直接下载。我们无法改变服务器发送的数据类型,于是我们尝试在客户端层面解决问题。
解决思路
用Blob类型接受response然后本地改变Content-Type到application/pdf
,再用本地数据渲染。
问题解决
首先,我们需要以Blob类型处理response,然而据说jquery处理blob类型有许多问题(事实上笔者也确实碰到了问题),所以我们换用普通的Ajax:
1 | var req = new XMLHttpRequest(); |
接下来,我们发现Blob的类型还是octet-stream
,直接放入object中仍然失败,所以我们需要修改其type
。然而Blob是immutable的,我们无法直接修改其参数。根据本文,我们这么修改blob
的类型:
1 | //hacky solution!! |
最后我们使用非常强大的URL工具创建本地URL:
1 | if(para1.endsWith(".pdf")){ |
该URL会随着document卸载而卸载,本场景下不用手动卸载。
(欸,我的代码中的美元都到哪去了?)
重点
- 如何获取服务器上的Blob数据
- 如何修改Blob的类型
- 如何用Blob创建本地URL