For reference, a record of the problems encountered at ordinary times
1. Ordinary download
When the resource returned by the backend is a link, you can use the a
tag or window.location.href
to open it directly.
1, a label form
In H5, the a
tag has a new download
attribute. When a link containing this attribute is clicked, the browser will download the link on the href attribute by downloading a file.
<a href="https://example.com" download="example.html">下载</a>
// 或者封装
function download(href, title) {
const a = document.createElement('a');
a.setAttribute('href', href);
a.setAttribute('download', title);
a.click();
}
download('https://example.com', 'test')
2. Open window.location.href directly
window.location.href === 'https://example.com'
2. Streaming file download
When the file returned by the backend is a streaming file, take the umi-request
request method as an example
First, set the return type in the request: responseType: "blob"
import request from "umi-request";
export const downLoad = (url, fileName) =>
request(url, {
method: "POST",
data: data,
responseType: "blob", // 代表内存之中的一段为二进制
}).then(data) => {
const blob = data;
let link = document.createElement("a");
link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
link.download = fileName;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
};
1. Customize the file name
At this point, you can find that the backend returns a stream file, and the front end receives garbled characters. When you customize the file name on the front end, you can download it directly
downLoad('https://example.com/api/download', 'test.xlsx')
2. Use the file name defined by the backend
When the back-end fileName
is used, the file name defined in the content-disposition
should be obtained at this time.
First call the interface and find that the file name is in the request header content-disposition
. It should be noted that although we can see it, we cannot get the request header.
If you want the browser to be able to access other response headers, you need to set Access-Control-Expose-Headers
// 后端面大致写法
headers.add("Access-Control-Expose-Headers", "Content-Disposition");
At this time, you can get the relevant information and find that it is encoded, and you need decodeURI to decode
const disposition = response.headers.get('Content-Disposition');
const fileName = decodeURI(disposition.split(";")[1].split("filename=")[1])
Note: The request header information cannot be obtained directly in the request method, and the request needs to be intercepted
request.interceptors.response.use(async (response) => {
const disposition = response.headers.get("Content-Disposition"); // 获取Content-Disposition
return disposition // 当Content-Disposition中有值的时候进行处理,其他请求的响应则放过
? {
blob: await response.blob(), // 将二进制的数据转为blob对象,这一步是异步的因此使用async/await
fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理Content-Disposition,获取header中的文件名
}
: response;
});
The complete code is as follows:
request file
import request from "umi-request";
// 响应拦截
request.interceptors.response.use(async (response) => {
const disposition = response.headers.get("Content-Disposition"); // 获取Content-Disposition
return disposition // 当Content-Disposition中有值的时候进行处理,其他请求的响应则放过
? {
blob: await response.blob(), // 将二进制的数据转为blob对象,这一步是异步的因此使用async/await
fileName: decodeURI(disposition.split(";")[1].split("filename=")[1]), // 处理Content-Disposition,获取header中的文件名
}
: response;
});
export const downLoadExcel = (url) =>
request(url, {
method: "POST",
data: data,
// responseType: "blob", // 注释掉这一段
}).then(data => {
const { blob, fileName } = response;
let link = document.createElement("a");
link.href = URL.createObjectURL( new Blob([blob], { type: "application/vnd.ms-excel" }) );
link.download = fileName;
document.body.appendChild(link);
link.click();
URL.revokeObjectURL(link.href);
document.body.removeChild(link);
});
react file
<Buttton onClick={download}> 下载 </Button>
js file
async download() {
await downLoadExcel('http://example.com/api/download');
},
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。