前几天做builder项目有个pdf下载需求,然后把在做这个的问题和方法记录下来(仅供参考)。
1.概念
有些同学很有可能会疑问,pdf下载和预览功能,什么时候是下载?什么时候是预览?
其实这个和几方面的因素有关系,假如一个a标签,herf指向个路径 ,如下图:
那么默认情况打开是预览的(如果浏览器有插件是直接预览的):
那么如果服务端做了对文件配置(我到网站随便copy的一段,nginx服务端配置pdf文件下载):
那么所有做过滤的文件都会变成下载状态!
如果你去往服务器发送请求,通过接口去请求pdf文件的话,那么接口的response通过响应头也可以控制。
下载 (attachment):
inline(预览):
如果一个文件又需要下载,又需要预览怎么办?
同一个服务器上是做不到的,除非在不用的服务器上。
1.实现
有了上面的概念再来说说怎么实现的,之前一直以为如果后端接口返回一个文件流给我,前端这边只要请求成功的话是可以直接下载的,结果偏偏不是,接口返回来的是一段乱码(二进制的),不知道是啥玩意,看下图:
如果碰到这种情况,你在请求头里面一定要配置responseType: “blob”,因为只有它才能解析二进制的文件:
RESTfulService.prototype.templatedownload = function (parameters) {
var that = this;
var url = that.CGP_REST + that.API + 'materialViewTypePrecessConfigController/template/download';
return this.$http({
method: "GET",
url: url,
params: parameters,
responseType: "blob"
})
};
之前用的是$resource,不知道什么问题(配了responseType: "blob"也解析不了),因为项目用的是angular,所以后来改成了 angular的 $http(如果知道原因的话,可以分享下!)
然后拿到response结果后,要创建blob对象去解析这个二进制文件流:
var blob = new Blob([response.data], {
type: response.data.type
});
var pdf = document.createElement('a');
pdf.href = window.URL.createObjectURL(blob);
pdf.download = 'template.pdf';
document.body.appendChild(pdf);
pdf.click();
pdf.remove();
window.URL.revokeObjectURL(pdf.href);
或者还有一种另外的方法,参数就是请求的接口地址(直接简单粗暴):
window.open('http://192.168.41.161:8080/api/materialViewTypePrecessConfigController/template/download?sbomPath=1947217&ssmvtId=2025302&propertyModelId=2036805&access_token=b4c6102f-2c7f-45c3-ad5d-001f7b707300')
这种简单粗暴的方式缺陷就是抓不到请求的之后成功或者失败的状态!如果请求失败了需要再次retry的话这个你就不知道它的状态了!不好控制!方法有很多种,可以自己去尝试!好了说到这里都已经说的差不多了,有不正的地方请指正,不胜感激!!欢乐的时光总是过得特别快,又到时候和大家讲拜拜!!