前端下载文件的几种方式
1、使用 location.href
// 适用于浏览器无法识别文件,如果是html、jpg、pdf等会直接解析展示,而不会下载
window.location.href = url
2、使用 window.open
// 适用于浏览器无法识别文件,如果是html、jpg、pdf等会直接解析展示,而不会下载
window.open(url)
3、a 标签
// 适用于单文件下载或需要自定义文件名称 //写法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">
4、文件流
step1 发送请求,有两种方式
// 此种方式的优点是支持多文件下载、post下载、自定义文件名称,流程是向后端发送post请求,后端返回文件流,前端将文件流转成下载链接 // 原生js请求写法(不可以使用JQuery,因为JQuery不支持blob类型) function download() { const req = new XMLHttpRequest(); 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请求写法 function download() { axios({ method: 'post', headers: { 'Content-Type': 'application/json; charset=utf-8' }, url: '/robot/strategyManagement/analysisExcel', responseType: 'blob', headers: { //如果需要权限下载的话,加在这里 Authorization: '123456' } data: JSON.stringify(params), }).then(function(res){ var content = res.headers['content-disposition']; var name = content && content.split(';')[1].split('filename=')[1]; var fileName = decodeURIComponent(name) downloadFile(res.data,fileName)// 调用将文件流转成文件的方法,后面有写 }) }
step2 处理文件流下载
方式一: 通过URL.createObjectURL()下载
// URL.createObjectURL() 静态方法会创建一个DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的document绑定 downloadFile:function(data,fileName){ // data为blob格式 var blob = new Blob([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 = 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) } }
readAsDataURL 和 createObjectURL 对比
readAsDataURL (blob) | createObjectURL (blob) | |
返回值 | 可以得到一段base64的字符串 | 得到的是当前文件的一个内存url |
内存 | js垃圾回收机制自动从内存中清理 | 存在于当前document内,清除方式通过revokeObjectURL()手动清除 |
执行方式 | 通过回调的方式f返回,异步执行 | 直接返回,同步执行 |
多个文件 | 同时处理多个文件时,需要一个文件对应一个FileReader对象 | 依次返回,没有影响 |
优势对比 | 可直接转为base64格式,直接用于业务 | 得到本地内存容器的URL地址,方便预览,需要注意手动释放内存的问题,性能优秀 |
只要你不觉得尴尬,那尴尬的就是别人