axios无法获取响应头headers的Content-Disposition

1.问题描述

发送协议请求一个文件流,需要在回包里拿到响应头里的Content-Disposition字段的值,从中分离出文件名。但是通过查看控制台,header里确实有这个属性:

img

在控制台Network里明明能看到,但是在响应拦截器里用js headers["content-disposition"]来获取,但是打印 header对象里并没有content-disposition,无法获取,这是什么原因?

2、原理(病灶)Access-Control-Expose-Headers

根据MDN文档:Access-Control-Expose-Headers

默认情况下,header只有六种 simple response headers (简单响应首部)可以暴露给外部:

  • Cache-Control
  • Content-Language
  • Content-Type
  • Expires
  • Last-Modified
  • Pragma

这里的暴露给外部,意思是让客户端可以访问得到,既可以在Network里看到,也可以在代码里获取到他们的值。

上面问题提到的content-disposition不在其中,所以即使服务器在协议回包里加了该字段,但因没“暴露”给外部,客户端就“看得到,吃不到”。

而响应首部 Access-Control-Expose-Headers 就是控制“暴露”的开关,它列出了哪些首部可以作为响应的一部分暴露给外部。

所以如果想要让客户端可以访问到其他的首部信息,服务器不仅要在heade里加入该首部,还要将它们在 Access-Control-Expose-Headers 里面列出来。

3.解决

后端设置

response.setHeader("Access-Control-Expose-Headers", "Content-Disposition")
response.setHeader("Content-Disposition", ...)

成功设置后,服务台Network可以看到:

img

最终,js就能获取到响应header的Content-Disposition字段的值了。

4、直接从response下载的方法

/**
 * desc: 文件下载 导出结果处理  type:文件类型 zip .xls .xlsx ...
 */
export function handleDownLoadFile(response, type, fileName) {
    let blob = new Blob([response], {
        type: type + ';charset=utf-8'
    });
    let src = window.URL.createObjectURL(blob);
    if (src) {
        let link = document.createElement('a');
        link.style.display = 'none';
        link.href = src;
        link.setAttribute('download', fileName);
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link); //下载完成移除元素
        window.URL.revokeObjectURL(src); //释放掉blob对象
    }
}
Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐