1 案例
通过 fetch 发起请求获取文件,再用 Blob 对象来接收处理。接收到后端返回的文件后,将其放入 a 标签 的 href,并触发下载行为。实现的代码如下:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 
 | const formData = new FormData();formData.append("msg", "download");
 
 fetch(url, {
 method: "POST",
 body: formData,
 headers: new Headers({ "Content-Type": "application/json;charset=UTF-8" }),
 })
 .then((response) => {
 return response.blob();
 })
 .then((blob) => {
 const link = document.createElement("a");
 link.style.display = "none";
 link.href = URL.createObjectURL(blob);
 document.body.appendChild(link);
 link.click();
 
 URL.revokeObjectURL(link.href);
 document.body.removeChild(link);
 });
 
 | 
注意:调用 response 的 blob 方法会返回一个 promise 对象
2 处理文件名
上一个步骤下载得到的文件名是无意义的。假设服务端把文件名放在 content-disposition 头:
| 12
 3
 4
 5
 
 | response.setContentType("application/octet-stream");response.setHeader("Access-Control-Expose-Headers", "Content-disposition");
 response.setHeader("Content-disposition", "attachment;filename=" + fileName);
 response.flushBuffer();
 workbook.write(response.getOutputStream());
 
 | 
前端可采用 split 方法提取。完整实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | fetch(url, {method: "POST",
 body: formData,
 headers: new Headers({ "Content-Type": "application/json;charset=UTF-8" }),
 }).then(function (response) {
 const filename = res.headers
 .get("content-disposition")
 .split(";")[1]
 .split("=")[1];
 
 response.blob().then((blob) => {
 const link = document.createElement("a");
 link.style.display = "none";
 link.download = filename;
 link.href = URL.createObjectURL(blob);
 document.body.appendChild(link);
 link.click();
 
 URL.revokeObjectURL(link.href);
 document.body.removeChild(link);
 });
 });
 
 | 
注:a 标签的 download 属性就是文件名
或者用 async/await 实现:
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 
 | async function download(url) {const request = {
 method: 'POST',
 body: formData,
 headers: new Headers({ "Content-Type": "application/json;charset=UTF-8" }),
 }
 
 const response = await fetch(url, request)
 const filename = response.headers.get('content-disposition').split(';')[1].split('=')[1]
 const blob = await response.blob()
 
 const link = document.createElement('a')
 link.download = decodeURIComponent(filename)
 link.style.display = 'none'
 link.href = URL.createObjectURL(blob)
 document.body.appendChild(link)
 link.click()
 URL.revokeObjectURL(link.href)
 document.body.removeChild(link)j
 }
 
 |