vue项目中下载文件踩过的坑(一)


很多的系统管理端会有文件上传或者下载功能,那么在文件上传和下载的时候我们又会遇到什么样的坑人的意外呢?

昨天我们在做管理系统的文件下载时,遇到了这么一个问题。因为文件名是后端提供,所以返回在了响应头的Content-Disposition中,但是因为这个字段并不是默认暴露的字段,所以需要后端做暴露(加上这句代码)

Access-Control-Expose-Headers: Content-Disposition

  在前端接收到后端暴露的响应头字段时,在请求拦截器中拿到并处理返回数据

 1 service.interceptors.response.use(
 2   response => {
 3     if (response.request.responseType === 'arraybuffer' && !response.headers['content-disposition']) {
 4       //当没有content-disposition这个字段时return的数据
 5       return response.data 
 6     }
 7     if (response.request.responseType === 'arraybuffer' && response.headers['content-disposition']) {
 8       //当存在content-disposition这个字段时,return出来的数据
 9       const temp = {}
10       temp.data = response.data
11       temp.filename = response.headers['content-disposition']
12       return temp
13     }
14     const res = response.data
15     if (res.success) {
16       return response.data
17     } else {
18       Message({
19         message: res.message,
20         type: 'error',
21         duration: 5 * 1000
22       })
23       return Promise.reject(res.message)
24     }
25   }
26 )

当我们下载文件时返回了文件名,下载文件模板时没有返回文件名

 1 getDocData(data) {
 2       const params = {
 3         id: data
 4       }
 5       GiftApi.exportDoc(params).then(res => { //返回文件名的写法
 6         this.content = res.data
 7         const filename = res.filename.split(';')[1].split('=')[1]
 8         this.filename = decodeURI(filename)
 9         const blob = new Blob([this.content])
10         if (window.navigator.msSaveOrOpenBlob) {
11           // 兼容IE10
12           navigator.msSaveBlob(blob, this.filename)
13         } else {
14           //  chrome/firefox
15           const aTag = document.createElement('a')
16           aTag.download = this.filename
17           aTag.href = URL.createObjectURL(blob)
18           aTag.click()
19           URL.revokeObjectURL(aTag.href)
20         }
21       })
22     }
23 
24 getDocData(data) {
25       const params = {
26         id: data
27       }
28       GiftApi.exportDoc(params).then(res => { //未返回文件名的写法
29         this.content = res
30         this.filename = this.temp.name + '.doc'
31         const blob = new Blob([this.content])
32         if (window.navigator.msSaveOrOpenBlob) {
33           // 兼容IE10
34           navigator.msSaveBlob(blob, this.filename)
35         } else {
36           //  chrome/firefox
37           const aTag = document.createElement('a')
38           aTag.download = this.filename
39           aTag.href = URL.createObjectURL(blob)
40           aTag.click()
41           URL.revokeObjectURL(aTag.href)
42         }
43       })
44     }

这样的代码本身没有错误,而且在本地和测试服务器上测试的时候也没有问题,但是打包之后的测试会存在问题,就是未返回文件名的接口下载的文件,打开会出现[object,object],而不是我们文件原本的内容。所以我的解决方法就是让后端统一返回文件名并把该字段暴露出来让前端能获取到,渲染和处理数据的格式一样,就不会出现打包之后下载文件出错的问题