引言
最近在自己做项目的需求的过程中,需要vue+springboot
实现文件的下载功能(导出博客文件)。
问题重现
在我后端文件下载接口开发完成后,使用vue前端去进行对接时出现了问题。
我是直接使用的axios
去进行请求接口,请求接口后返回的状态码是200,但是就是不会自动下载文件。
起初我一直以为是我后端接口有问题,后才发现我们如果在vue中通过button
发送axios请求文件下载的接口,那么是不会去进行自动下载文件的,必须要在a标签中去进行调用,才会自动下载文件,所以我们在axios请求完成后,在js中去调用a标签即可
问题解决
经过寻找资料,发现vue通过axios请求后是不会自动下载文件的,需要我们自己去做一些配置(只能通过a标签去进行文件的下载)
-
axio中需要添加
responseType
,以此来辨别它的请求类型responseType
为blob
即可export function exportArticleList(data){ return request({ url: '/article/exportArticleList', method: 'post', data: data, responseType: 'blob' }) }
-
后端返回response后,我们需要做些处理,我们需要使用a标签将其打开下载,如下示例:
由于我前端使用的
vue-admin-template
模板,所以直接在request.js
中进行response
统一处理即可。如果返回的
response
中的headers
中content-type
的值为application/octet-stream;charset=UTF-8
,则我们判定它有需要下载的文件,然后我们调用a标签来进行下载**注意:**vue的
response
可能获取不到content-disposition
的值,我们需要在后端进行对于处理才行后端处理:
//在vue的response中显示Content-Disposition response.setHeader("Access-Control-Expose-Headers", "Content-Disposition"); // 设置在下载框默认显示的文件名 response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8")+".zip");
const res = response.data console.log(response) //获取请求的类型 const respContentType = response.headers['content-type'] if (respContentType === 'application/octet-stream;charset=UTF-8') { console.log("有文件类型的流") if (!res) { return } //由于后台返回文件名称是通过response返回的 //因此需要从response headers中content-disposition响应头中获取文件名称fileName let fileName = response.headers["content-disposition"]; fileName = fileName.split('=')[1] const url = window.URL.createObjectURL(new Blob([res], { type: 'application/octet-stream;charset=UTF-8' })) const link = document.createElement('a') link.style.display = 'none' link.href = url //decodeURIComponent解决文件名的url转码问题 link.setAttribute('download', decodeURIComponent(fileName)) document.body.appendChild(link) link.click() document.body.removeChild(link) return }
解决完成
点击导出可以成功下载文件
其它问题
URL转码问题
由于后端传来前端的文件名是经过url转码的,所以中文会出现乱码的情况
vue中使用如下命令即可进行解码
// 解码用
decodeURIComponent(str)
// 编码用
encodeURIComponent(str)