平时在前端下载文件有两种方式,一种是后台提供一个 URL,然后用 window.open(URL) 下载,另一种就是后台直接返回文件的二进制内容,然后前端转化一下再下载。
mdn 上是这样介绍 Blob 的:
Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是 JavaScript 原生格式的数据
注意事项:
arraybuffernew Blob 时,要给不同文件对应的 type ,详见 MIME 类型列表预览文件代码示例:
axios({
method: "post",
url: "/export",
// 需要设置服务器响应的数据类型为arraybuffer
responseType: "arraybuffer"
}).then((res) => {
// 假设 data 是返回来的二进制数据
const data = res.data;
const url = window.URL.createObjectURL(
// type设置文件类型
new Blob([data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
})
);
window.open(url);
});
下载文件代码示例:
axios({
method: "post",
url: "/export",
responseType: "arraybuffer"
}).then((res) => {
const data = res.data;
const url = window.URL.createObjectURL(
new Blob([data], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
})
);
const link = document.createElement("a");
link.style.display = "none";
link.href = url;
link.setAttribute("download", "excel.xlsx");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(url);
});

const res = await weekExport();
const enc = new TextDecoder("utf-8");
// 如果正常返回,需要后端把arraybuffer放在{"code":"200","msg":"ok","data":二进制流}的data里,否则这样写会报错,或者考虑使用try catch
const resData = JSON.parse(enc.decode(new Uint8Array(res as any))); // 转化成json对象
if (resData.code !== "200") {
ElMessage.error(resData.msg);
}
request.interceptors.response.use(
(response) => {
// 失败时res为{"code":"200","msg":"失败","data":null}的二进制流
// 成功时res为文件二进制流
const res = response.data
loading.hide()
if (response.config.responseType === 'arraybuffer') {
try {
const enc = new TextDecoder('utf-8')
// res为文件二进制流时 JSON.parse会报错
const resData = JSON.parse(enc.decode(new Uint8Array(res)))
if (resData.code !== '200') {
ElMessage.error(resData.msg || 'Error')
return Promise.reject(response.data || 'Error')
}
} catch (error) {
return res
}
}
//......
},
(error) => {
// ......
);
// 将文件地址转化成blob
export const getBlob = (url: string) => {
return new Promise((resolve) => {
const xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "blob";
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response);
}
};
xhr.send();
});
};
// 将blob保存成本地文件
export const saveAs = (blob: any, filename: string) => {
const link = document.createElement("a");
link.href = window.URL.createObjectURL(blob);
link.download = filename;
link.click();
};
const blob = await getBlob(http://it.test.survey.shuzhe.com:8001/Upload/person-cloud/Upload/Other/20230223/2302196607700001.docx);
saveAs(blob, 'test.docx');