对于现代的前端来说,使用vue项目搭配上异步axios是比较常见的,但是当通过ajax请求的时候,浏览器并不会自动响应下载,所以就需要前端进行封装,模拟一个下载操作。
比如像下面这样
javascript
export function batchPrint(params) {
return request({
url: '/reimburse/batch-print',
method: 'post',
data: params,
responseType: 'blob'
}).then((res: any) => {
// 创建blob对象
const blob = new Blob([res], { type: 'application/zip' })
// 生成文件名(使用时间戳作为默认文件名)
const fileName = `报销单批量打印_${new Date().getTime()}.zip`
// 创建下载链接
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
// 释放URL对象
URL.revokeObjectURL(link.href)
return res
})
}
接收到二进制,封装为blob,并用URL生成一个临时url,通过a标签模拟一个下载请求。
那为何不能直接进行下载了呢,那是因为对于浏览器来说,ajax请求是异步请求,并不会自动触发。
java
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Content-Disposition",
"attachment;filename=" + URLEncoder.encode(zipFileName, "UTF-8"));
response.setContentType("application/zip");
那后端设置的响应头还有意义吗,实际是意义不大,因为在前端获取的时候,只使用了res.data也就是二进制流,而忽略了response的内容。
但是有人就会问,那我只在后端的响应头里面封装了文件的名字,前端获取不到,重新设置了名字,这不是多此一举吗?

这里有一个细节,因为我使用的是若依框架,在request.js里面

他设置了在获取blob的时候,只让data保留,其他的全部扔掉,所以你的方法里面也无法获取到response里面的内容。
如果你是图片或者pdf,你可以通过链接打开方式,来变成预览。
javascript
// 创建blob对象 - res直接就是blob数据
const blob = new Blob([res], {type: 'application/pdf'})
// 生成文件名(使用时间戳作为默认文件名)
const fileName = `reimburse_c${id}${new Date().getTime()}mc.pdf`
// 创建下载链接
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
//link.download = fileName
document.body.appendChild(link)
//link.setAttribute('download', fileName)
link.target = '_blank'
link.click()
document.body.removeChild(link)
// 释放URL对象
URL.revokeObjectURL(link.href)
return res
对于响应头的设置,具体可以看MDN。