文件下载方式

176 阅读3分钟

一.后端返回文件地址

1.window下载

对于一些浏览器无法识别的文件格式,可以直接再浏览器地址栏输入url即可触发浏览器的下载功能。对于单文件下载没有什么问题,但是如果下载多文件,点击过快就会重置掉前面的请求

适用场景:

  • get请求
  • 单文件下载

window.location.href = url;

window.open(url);

2.a标签下载

对于浏览器支持的文件格式,如html、jpg、png、pdf等,输入地址则不会触发文件下载,而是直接被浏览器解析并展示,这种情况下,可以使用a标签下载文件,download属性可以设置文件名。适用于单文件下载,如果下载多文件,点击过快就会重置掉前面的请求。

适用场景:

  • get请求
  • 单文件下载
  • 需要自定义文件名
//写法1
const download = (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">

跨域情况下(https请求http)

  • download 设置无效
  • 图片等能被浏览器直接打开的资源会在浏览器中直接打开,而没有被下载成文件
  • 利用setAttribute设置属性
const download = (filename, url) => { let a = document.createElement('a');
a.style = 'display: none'; // 创建一个隐藏的a标签 
a.setAttribute('href', newUrl); 
a.setAttribute('target', '_blank'); 
a.setAttribute('download', filename); 
document.body.appendChild(a); 
a.click(); // 触发a标签的click事件 
document.body.removeChild(a); }

二.后端返回文件流

如果需要使用post请求,且后端返回是一个文件流形式,那么前端需要自己将文件流转成链接,然后下载。

适用场景:

  • post请求
  • get请求
  • 多文件
  • 后端返回文件件流和json两种格式
axios({ method: 'POST', url: URL, data: params, headers: configHeaders, responseType: 'blob', })
.then( (res) => {
//为blob格式准备下载 
var content = res.headers['content-disposition']; 
var name = content && content.split(';')[1].split('filename=')[1]; 
var fileName = decodeURIComponent(name) 
//下载文件 
this.downloadFile(res.data,fileName) 
},

文件流下载方式

URL.createObjectURL()

FileReader.readAsDataURL()

//通过URL.createObjectURL()下载 
  downloadFile:function(data,fileName){ 
// data为blob格式 
  let blob = new Blob([data]); 
  let downloadElement = document.createElement('a'); 
  let 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()下载 
  downloadFile:function(data,fileName){ 
  const reader = new FileReader() 
// 传入被读取的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格式,直接用于业务

三.后端返回文件流和json两种格式

需要判断返回文件类型,并通过FileReader讲blob转换为JSON

axios({ method: 'POST', 
        url: URL, 
        data: params, 
        headers: configHeaders, 
        responseType: 'blob', 
        }).then( (res) => { 
        //判断后端返回文件格式,如果为JSON格式 
        if (res.data.type == 'application/json') { 
        // 通过FileReader读取blob数据为string 
        const reader = new FileReader(); 
        reader.readAsText(res.data, 'utf-8'); 
        //读取文件,结果用字符串形式表示 
        reader.onload = function() { 
        //读取完成后,**获取reader.result** 
        const { msg } = JSON.parse(reader.result); 
        console.log(JSON.parse(reader.result)); 
        //弹出错误提示 
        that.$message.warning(msg); }; 
        return;
        } 
        //正常blob下载代码
           .....
        },