前端文件下载
<a href="链接" >下载</a>
一个文件链接(一般是服务器上的某个文件),这个链接一般地址栏输入是预览,不是附件下载
如果想改成附件下载
1、后端处理,后端加上一个响应头
res.setHeader('Content-Dispostion', 'attachment', 'name.pdf')
然后当你访问这个链接,浏览器发现有这个相应头,会自动触发下载行为
2、a标签 加上 download属性
<a href="链接" download="文件名" >下载</a>
这种也可以,但是局限性太大,
如果这个文件的下载要求的是携带token,那a标签这种就不生效了(a标签没法携带token)。会成为预览
方案:a标签可以携带cookie,所以可以有另一种解决方法,在下载文件前,发送一个请求获取一个临时token通过cookie进行携带,
a标签下载是流式下载,会把服务器的文件像流水一样存储到本地磁盘,所以下载直接能看到下载,不会将文件缓存到浏览器,
3、写一个方法进行下载 (本质还是利用a标签进行下载)
这个方法可以是一个ajax请求,这个请求就可以携带token,然后将请求到的服务器文件转成blob,在创建一个a标签进行下载,
但是**这种是有问题的,**如果文件小还行,文件大了就会出现点击了下载,但是没有反应,过了几分钟后才出现了下载,
这种等待时间就是将服务器端的那个文件转成了blob,才进行a标签的流式下载,
//获取blob
export function handleGetBlob(url) {
// console.log(url)
return new Promise((resolve) => {
const xhr = new XMLHttpRequest()
xhr.open('GET', url, true)
xhr.responseType = 'blob'
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response)
}
}
xhr.setRequestHeader('Cache-Control', 'no-cache')
xhr.send()
})
}
/**
* 下载入口
*/
export function downloadFile(url, name) {
return new Promise((resolve, reject) => {
handleGetBlob(url)
.then((blob) => {
let fileName = url.split('/')
let fileType = ''
fileName = fileName[fileName.length - 1]
fileType = fileName.split('.')
fileType = fileType[fileType.length - 1]
let saveName = `${name}.${fileType}`
if (name.indexOf('.') > -1) {
saveName = name
const lastType = name.split('.')[name.split('.').length - 1]
if (fileType && lastType !== fileType) {
saveName = `${name}.${fileType}`
}
}
handleSaveAs(blob, saveName)
resolve()
})
.catch((err) => {
console.log('err', err)
reject(err)
// this.$message.warning('下载错误');
})
})
}
/**
* 下载文件并重新命名
*/
export function handleSaveAs(blob, filename) {
if (window.navigator.msSaveOrOpenBlob) {
navigator.msSaveBlob(blob, filename)
} else {
const link = document.createElement('a')
const body = document.querySelector('body')
link.href = window.URL.createObjectURL(blob)
link.download = filename
// fix Firefox
link.style.display = 'none'
body.appendChild(link)
link.click()
body.removeChild(link)
window.URL.revokeObjectURL(link.href)
}
}