前端文件下载
1.最简单直接的方式
没有下载进度、不能鉴权、浏览器支持预览的不提供下载、url长度问题
window.open('file') window.location.href = 'file'
|
2.a标签的download
(浏览器兼容性良好、不支持跨域、不能鉴权)
<a href="example.jpg" download>点击下载</a>
|
带上属性值,重命名下载文件名
<a href="example.jpg" download="test">点击下载</a>
|
检测是否支持download
const isSupport = 'download' in document.createElement('a');
|
3.Blob对象下载
它除了能利用已知文件地址路径进行下载外,还能通过发送ajax请求api获取文件流进行下载
downloadFile (path, name) { const xhr = new XMLHttpRequest(); xhr.open('get', path); xhr.responseType = 'blob'; xhr.send(); xhr.onload = function () { if (this.status === 200 || this.status === 304) { if ('msSaveOrOpenBlob' in navigator) { navigator.msSaveOrOpenBlob(this.response, name); return; } const url = URL.createObjectURL(this.response); const a = document.createElement('a'); a.style.display = 'none'; a.href = url; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); } }; }
|
该方法不能缺少a标签的download属性的设置。因为发请求时已设置返回数据类型为Blob类型(xhr.responseType = 'blob'),所以target.response就是一个Blob对象,打印出来会看到两个属性size和type。虽然type属性已指定了文件的类型,但是为了稳妥起见,还是在download属性值里指定后缀名,如Firefox不指定下载下来的文件就会不识别类型。
如果发送请求时不设置xhr.responseType = 'blob',默认ajax请求会返回DOMString类型的数据,即字符串。这时就需要两处注释的代码了,对返回的文本转化为Blob对象,然后创建blob url,此时需要注释掉原本的const url = URL.createObjectURL(target.response)。
4.Base64方式下载
downloadFile (path, name) { const xhr = new XMLHttpRequest(); xhr.open('get', path); xhr.responseType = 'blob'; xhr.send(); xhr.onload = function () { if (this.status === 200 || this.status === 304) { const fileReader = new FileReader(); fileReader.readAsDataURL(this.response); fileReader.onload = function () { const a = document.createElement('a'); a.style.display = 'none'; a.href = this.result; a.download = name; document.body.appendChild(a); a.click(); document.body.removeChild(a); }; } }; }
|
5.文件名相关
有可能是后端提供、前端获取文件名,header中Content-Disposition通常有两种形式**filename=*和filename=
提取文件名
// xhr是XMLHttpRequest对象 const content = xhr.getResponseHeader('content-disposition'); // 注意是全小写,自定义的header也是全小写 if (content) { let name1 = content.match(/filename=(.*);/)[1]; // 获取filename的值 let name2 = content.match(/filename\*=(.*)/)[1]; // 获取filename*的值 name1 = decodeURIComponent(name1); name2 = decodeURIComponent(name2.substring(6)); // 这个下标6就是UTF-8'' } // 可能浏览器只支持UTF-8的
|
6.重命名文件
export const findType = ((name) => { const index = name.lastIndexOf('.') return name.substring(index+1); })
|