一、第一种方式是前端创建超链接,通过a标签的链接向后端服务发get请求或者是window.location.href,接收后端的文件流
const download = (url, fileName) => {
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName)
document.body.appendChild(link)
link.click()
}
location.href或者是a标签直接指向一个文件的话,浏览器会下载该文件,对于单文件下载没有什么问题,但是如果下载多文件,点击过快就会重置掉前面的请求,href链接静态资源而且适用于浏览器无法识别文件,如果是html、jpg、pdf等会直接解析展示,而不会下载
<a href="https://www.clzczh.top/medias/test.html">下载文件</a>
window.open可以打开一个新窗口,虽然能通过这种方式下载文件,但是新的窗口不会关闭,明显体验上不好
二、方式通过创建form表单的方式
利用form表单提交能发起浏览器请求,并且也可以作为多文件下载来使用
var params = {// 参数
id:xx,
name:xx
};
var form = document.createElement('form')
form.id = 'form'
form.name = 'form'
document.body.appendChild (form)
for (var obj in params) {
if (params.hasOwnProperty(obj)) {
var input = document.createElement('input')
input.tpye='hidden'
input.name = obj;
input.value = params[obj]
form.appendChild(input)
}
}
form.method = "GET" //请求方式
form.action = runEnv.api_url+'请求地址'
form.submit()
document.body.removeChild(form)
},
三、会对后端发的post请求,使用blob格式,后端返回文件二进制流
mdn 上是这样介绍 Blob 的:
Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据,axios,设置responseType: 'arraybuffer',接收二进制流
axios({
method: 'post',
url: '/export',
responseType: 'arraybuffer',
})
.then(res => {
// 假设 data 是返回来的二进制数据
const data = res.data
const url = window.URL.createObjectURL(new Blob([data], {type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"}))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
const fileNames = res.headers['content-disposition'] // 获取到Content-Disposition;filename
const regFileNames = decodeURI(fileNames.match(/=(.*)$/)[1])
link.setAttribute('download', regFileNames)
document.body.appendChild(link)
link.click()
document.body.removeChild(link)
})
四、获取文件下载文件流的实时进度(进度条)
文件下载功能体验不友好,特别是下载一些比较耗时的文件,用户在页面上傻等不知道下载的进度是怎么样的,总以为是系统卡死了,所以需要一个进度显示
后台主要是要返回计算好的文件大小,否则上面前端计算进度的时候取的total永远是0,这个就是一个隐藏的坑。(请求返回头添加content-length)
export const dowloadFile = (data, callback) => {
return request({
url: 'file/downloadFile',
method: 'post',
responseType: 'blob',
data: data,
onDownloadProgress (progress) {
callback(progress)
}
})
}
async batchDownloadFile (id) {
this.percentage = 0
this.$refs.FileProgress.progressShow = true
const res = await batchDownloadFile(id, this.processCallback)
if (res.status !== 200) {
this.$message.warning('下载失败')
this.$refs.FileProgress.progressShow = false // 关闭进度条显示层
return false
}
const fileNames = res.headers['content-disposition'] // 获取到Content-Disposition;filename
const regFileNames = decodeURI(fileNames.match(/=(.*)$/)[1])
const url = window.URL.createObjectURL(new Blob([res.data]))
const link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', regFileNames)
document.body.appendChild(link)
link.click()
this.$refs.FileProgress.progressShow = false // 关闭进度条显示层
},
processCallback (progressEvent) {
const progressBar = Math.round(progressEvent.loaded / progressEvent.total * 100)
this.percentage = progressBar
},