前端主要代码
const xhr = new XMLHttpRequest();
xhr.onload = function (e) {
const blob = new Blob([xhr.response], { type: "application/octet-stream" });
const contentDisposition = xhr.getResponseHeader("Content-Disposition");
let link = document.createElement("a");
let fileName = "unknow.xxx";
if (contentDisposition) {
const descArrays = contentDisposition.split("=");
fileName = decodeURI(descArrays[1]);
}
link.href = window.URL.createObjectURL(blob);
link.download = fileName;
link.click();
link.remove();
window.URL.revokeObjectURL(link.href);
}
xhr.open(method, url);
xhr.send(params);
Java头信息设置
public static final String CONTENT_DISPOSITION = "Content-Disposition";
public static void setDownloadHeader(HttpServletResponse response, int len,
MediaType mediaType, String fileName) {
if (mediaType == null) {
mediaType = MediaType.APPLICATION_OCTET_STREAM;
}
fileName = URLEncoder.encode(fileName, StandardCharsets.UTF_8.name());
response.setCharacterEncoding(StandardCharsets.UTF_8.name());
response.setContentLength(len);
response.setContentType(mediaType.toString());
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.setHeader(CONTENT_DISPOSITION, "attachment;filename=" + fileName);
response.addHeader("Access-Control-Expose-Headers", CONTENT_DISPOSITION);
}
参考与说明
- new Blob(...)不设置 type,而下载又没有写文件类型后缀,chrome会默认当做txt格式
Content-Disposition默认不暴露给客户端,需要后端进行设置(见上文),参考: Access-Control-Expose-Headers | MDN
- 不给a标签download属性设置文件名,则浏览器会给出警告
Resource interpreted as Document but transferred with MIME type ...