使用Fetch()实现文件下载时无法设置自定义文件名的问题咨询
语法报错修复
你当前的报错是基础语法错误,第254行的解构参数缺少闭合右括号,正确写法如下:
.then( ({response, filename}) => {
文件名乱码/随机的根因与修复
先纠正两个误区
- 客户端请求头加
Content-Disposition完全无效,该字段是服务端返回的响应头,仅在响应阶段生效,你可以直接删掉客户端options里的这个头配置。 - 直接调用
window.location.assign跳转blob地址时,浏览器没有渠道获取自定义文件名,默认会把blob的UUID作为文件名,这是你拿到随机字符串文件名的核心原因。
修复步骤
- 服务端新增CORS暴露头配置
你当前的服务端Content-Disposition响应头配置逻辑是正确的,但默认情况下前端JS无法读取自定义响应头,需要在express的响应逻辑里新增暴露头配置:
res .set('Access-Control-Expose-Headers', 'Content-Disposition') // 新增这行,允许前端读取该响应头 .set('content-disposition', `attachment; filename="${filename}"; filename*=UTF-8''${encodeURI(filename)}`) .type('.xlsx') wb.write(filename, res);
- 适配无a标签调用的下载方案
如果不能使用a标签点击的方案,优先适配现代浏览器支持的File System Access API,示例代码如下:
fetch("/api") // 删掉没用的请求头配置 .then( res => { const filename = res.headers.get('Content-Disposition').split('filename=')[1].replace(/^"|"$/g, ''); return {blob: res.blob(), filename} }) .then( async ({blob, filename}) => { const fileBlob = await blob; const fileHandle = await window.showSaveFilePicker({ suggestedName: filename, types: [{ description: 'Excel文件', accept: {'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': ['.xlsx']} }] }); const writable = await fileHandle.createWritable(); await writable.write(fileBlob); await writable.close(); });
如果需要兼容旧版浏览器,可引入FileSaver polyfill实现下载,可自行修改polyfill底层逻辑规避a标签调用。
内容的提问来源于stack exchange,提问作者noszone
相关产品推荐
相关产品推荐

