前端实现文件下载
前端下载一般分为两种情况,一种是后端直接给一个文件地址,通过浏览器打开就可以下载,另外一种则需要发送请求,后端返回二进制流数据,前端解析流数据,生成URL,实现下载。
一、location.href
对于一些浏览器无法识别的文件格式,可以直接再浏览器地址栏输入url即可触发浏览器的下载功能。对于单文件下载没有什么问题,但是如果下载多文件,点击过快就会重置掉前面的请求
适用场景:
- get请求
- 单文件下载
window.location.href = url;
二、window.open
和location.href类似
window.open(url);
三、a标签
直接下载仅适用于浏览器无法识别的文件。如果是浏览器支持的文件格式,如html、jpg、png、pdf等,则不会触发文件下载,而是直接被浏览器解析并展示,这种情况下,可以使用a标签下载文件,download属性可以设置文件名。适用于单文件下载,如果下载多文件,点击过快就会重置掉前面的请求。
适用场景:
- get请求
- 单文件下载
- 需要自定义文件名
//写法1constdownload=(filename, url)=>{let a = document.createElement('a');
a.style ='display: none';// 创建一个隐藏的a标签
a.download = filename;
a.href = url;
document.body.appendChild(a);
a.click();// 触发a标签的click事件
document.body.removeChild(a);}// 写法2<a href="/images/download.jpg" download="myFileName">
注意:有时候对于浏览器可识别的文件格式,我们还是需要直接下载的情况,可以声明一下文件的header的 Content-Disposition信息,告诉浏览器,该链接为下载附件链接,并且可以声明文件名
Content-Disposition: attachment; filename="filename.xls"
四、文件流
如果需要使用post请求,且后端返回是一个文件流形式,那么前端需要自己将文件流转成链接,然后下载。 二进制流大概长这样: 适用场景:
- post请求
- get请求
- 多文件
1.请求的方式
注意:不可以使用JQuery,因为JQuery不支持blob类型。
原生js写法
const req =newXMLHttpRequest();
req.open('POST','/download/excel',true);
req.responseType ='blob';//如果不指定,下载后文件会打不开
req.setRequestHeader('Content-Type','application/json');
req.onload=function(){var content = req.getResponseHeader("Content-Disposition");// 文件名最好用后端返的Content-disposition// 需要后端设置 Access-Control-Expose-Headers: Content-disposition 使得浏览器将该字段暴露给前端var name = content && content.split(';')[1].split('filename=')[1];var fileName =decodeURIComponent(name)downloadFile(req.response,fileName)};
req.send(JSON.stringify(params));
axios写法
download(url: string,body: any,fileName: string, method?){returnaxios({method: method ||'post',headers:{'Content-Type':'application/json; charset=utf-8'},
url,responseType:'blob',headers:{//如果需要权限下载的话,加在这里Authorization:'123456'}data:JSON.stringify(params),timeout:60*1000}).then((res: any)=>{if(!res){
message.error('下载失败')return}
console.log('res:', res)let url = window.URL.createObjectURL(newBlob([res],{type:'application/vnd.ms-excel'}))let link = document.createElement('a')
link.style.display ='none'
link.href = url
if(!fileName ||typeof fileName !="string"){
fileName ="下载文件"}
link.setAttribute('download', fileName +'.xlsx')
document.body.appendChild(link)
link.click()
document.body.removeChild(link);//下载完成移除元素
window.URL.revokeObjectURL(url);//释放掉blob对象})}
2.文件下载的方式
通过URL.createObjectURL()下载
**
URL.createObjectURL()
** 静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的document绑定。
downloadFile:function(data,fileName){// data为blob格式var blob =newBlob([data]);var downloadElement = document.createElement('a');var href = window.URL.createObjectURL(blob);
downloadElement.href = href;
downloadElement.download = fileName;
document.body.appendChild(downloadElement);
downloadElement.click();
document.body.removeChild(downloadElement);
window.URL.revokeObjectURL(href);}
通过# FileReader.readAsDataURL()下载
**
readAsDataURL()
** 方法会读取指定的 Blob 或 File 对象。读取操作为异步操作,当读取完成时,可以从onload回调函数中通过实例对象的result属性获取data:URL格式的字符串(base64编码),此字符串即为读取文件的内容,可以放入a标签的href属性中。
downloadFile:function(data,fileName){const reader =newFileReader()// 传入被读取的blob对象
reader.readAsDataURL(data)// 读取完成的回调事件
reader.onload=(e)=>{let a = document.createElement('a')
a.download = fileName
a.style.display ='none'// 生成的base64编码let url = reader.result
a.href = url
document.body.appendChild(a)
a.click()
document.body.removeChild(a)}}
两者的区别
- 返回值
FileReader.readAsDataURL(blob)可以得到一段base64的字符串
URL.createObjectURL(blob)得到的是当前文件的一个内存url
- 内存
FileReader.readAsDataURL(blob)依照js垃圾回收机制自动从内存中清理 URL.createObjectURL(blob)存在于当前document内,清除方式通过revokeObjectURL()手动清除
- 执行方式
FileReader.readAsDataURL(blob)通过回调的方式f返回,异步执行
URL.createObjectURL(blob) 直接返回,同步执行
- 多个文件
FileReader.readAsDataURL(blob)同时处理多个文件时,需要一个文件对应一个FileReader对象
URL.createObjectURL(blob) 依次返回,没有影响
- 优势对比
URL.createObjectURL(blob)得到本地内存容器的
URL
地址,方便预览,需要注意手动释放内存的问题,性能优秀。
FileReader.readAsDataURL(blob)可直接转为
base64
格式,直接用于业务
五、插件downloadjs
下载
npm install --save downloadjs
引入插件
import download from"downloadjs"// orconst download =require('downloadjs')
使用
exportconstdownloadFile=(res, type, filename)=>{// 将二进制流转成blob对象const blob =newBlob([res],{type: type
})// 调用插件方法download(blob, filename, type);}
版权归原作者 MoXinXueWEB 所有, 如有侵权,请联系我们删除。