Skip to main content

文件下载

其实主要有以下几种方式实现文件下载

强制下载

阻止浏览器先预览文件

  1. 后端设置文件请求的响应头
Content-Disposition: attachment

浏览器收到响应,会强制下载文件,而不是预览

  1. 或者设置 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);

MDN-Content-Disposition

MDN-MIME

a 标签

<a href="url" download="xxx.png"></a>

a 标签的方式只有在非跨域情况才会正常下载。跨域情况下,浏览器还是会先尝试预览文件而不是直接下载

blob

  1. 从后端获取到二进制数据后,先将其转换为 Blob 对象
  2. 利用 URL.createObjectUrl 生成 ObjectURL
  3. 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",
});

参考