文件下载
其实主要有以下几种方式实现文件下载
强制下载
阻止浏览器先预览文件
- 后端设置文件请求的响应头
Content-Disposition: attachment
浏览器收到响应,会强制下载文件,而不是预览
- 或者设置 MIME 类型为以下:
content-type: application/octet-stream
这是应用程序文件的默认值,表示未知的应用程序文件。浏览器会像对待设置了 HTTP 头 Content-Disposition
值为 attachment
的文件一样来处理这类文件
然后通过 window.open
或者 location.href
让浏览器打开这个文件,从而实现文件下载。不过这里会有个闪屏的问题,可以考虑用一个隐藏的 iframe
优化
const iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = url;
iframe.onload = () => {
document.body.removeChild(iframe);
};
document.body.appendChild(iframe);
a 标签
<a href="url" download="xxx.png"></a>
a 标签的方式只有在非跨域情况才会正常下载。跨域情况下,浏览器还是会先尝试预览文件而不是直接下载
blob
- 从后端获取到二进制数据后,先将其转换为 Blob 对象
- 利用
URL.createObjectUrl
生成ObjectURL
- 将
ObjectURL
赋值在 a 标签的 href 属性上,结合download
属性进行下载。或者也可以通过file-saver
下载
// response.data 是后端传过来的二进制数据
let url = URL.createObjectURL(new Blob([response.data]));
let link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.download = `image.png`;
document.body.appendChild(link);
link.click();
如果是通过 ajax
请求,需要加上 reponseType: blob
,指定响应包含的数据类型为包含二进制数据的 blob 对象
XMLHttpRequest.responseType = "blob";
fetch 可以将响应转化为 blob 对象
fetch(url).then((res) => res.blob());
axios 在请求的时候配置一个字段即可
axios.get(url, {
responseType: "blob",
});