使用MSW模拟导出接口时Content-Disposition未触发自动下载问题
问题根因
你遇到的现象本质是浏览器的行为限制,和MSW模拟响应的逻辑无关:Content-Disposition: attachment 头触发自动下载的机制,仅对浏览器原生发起的同步导航请求生效,包括直接访问URL、原生表单提交跳转、<a>标签跳转这类场景。而你通过axios发起的是异步AJAX请求,浏览器默认不会对这类请求的响应执行下载操作,哪怕响应头配置完全符合要求也不会触发弹窗。
方案优化建议
你目前采用的生成ObjectURL触发下载的思路是正确的,只需要做两个小调整即可提升兼容性、避免内存问题:
- 替换
window.open()为动态创建<a>标签模拟点击,避免被浏览器弹窗拦截规则拦截 - 下载触发后主动释放ObjectURL,减少不必要的内存占用
优化后的store-module.js代码参考:
async exportThings(ctx, exportData) { const { docType, startDate, endDate, selected, } = exportData; const res = await services.exportThingsForStuff(ctx.state.id, docType, startDate, endDate, selected); if (res.data !== undefined) { const dataBLOB = new Blob([res.data], { type: res.headers['content-type'] }); const objUrl = URL.createObjectURL(dataBLOB); const tempLink = document.createElement('a'); tempLink.href = objUrl; // 从响应头提取文件名,提取失败则用默认命名 const contentDisposition = res.headers['content-disposition']; const fileName = contentDisposition?.match(/filename="?([^"]+)"?/)?.[1] || `export.${docType.split('/')[1]}`; tempLink.download = fileName; document.body.appendChild(tempLink); tempLink.click(); document.body.removeChild(tempLink); // 释放ObjectURL URL.revokeObjectURL(objUrl); } },
如果不想额外写前端处理逻辑,也可以把请求方式改成原生表单提交,浏览器就会自动识别Content-Disposition头触发下载,不需要异步请求处理。
内容的提问来源于stack exchange,提问作者D.Schaller
相关产品推荐
相关产品推荐

