React + Spring Boot项目下载大于10MB文件报Failed to fetch错误求助
问题排查与解决步骤
1. 修复CORS预检配置(匹配异常现象的核心原因)
你描述的「先下载小文件再下载大文件即可成功」的现象,本质是预检请求缓存导致的差异:
带Authorization头的请求属于非简单请求,浏览器会先发送OPTIONS预检请求校验跨域权限,校验通过才会发送真实的下载请求。小文件下载成功后,预检请求的结果会被浏览器短期缓存,后续大文件请求无需再发预检即可直接请求,因此可以成功。
修复方案:
在Spring Boot后端添加完整的CORS配置,显式设置预检缓存时长:
@Configuration class CorsConfig : WebMvcConfigurer { override fun addCorsMappings(registry: CorsRegistry) { registry.addMapping("/**") .allowedOrigins("http://localhost:你的前端服务端口") // 替换为实际前端地址 .allowedMethods("GET", "POST", "OPTIONS") .allowedHeaders("*") .exposedHeaders("Content-Disposition", "Content-Length") // 暴露下载必需的响应头 .maxAge(3600) // 预检结果缓存1小时,避免频繁触发预检 .allowCredentials(true) } }
2. 调整内嵌容器响应缓冲区配置
你遇到的10MB大小阈值,刚好匹配Spring Boot内嵌Tomcat的默认缓冲区大小,大于该阈值的响应会触发分块传输,配置不当会导致跨域失败。
修复方案:
在application.yml(或application.properties)中添加以下配置,将阈值调整为大于最大允许的25MB:
server: tomcat: max-swallow-size: 30MB spring: servlet: multipart: max-file-size: 30MB max-request-size: 30MB
如果你使用Undertow作为内嵌容器,对应调整server.undertow.max-http-post-size配置即可。
3. 优化前端下载代码
现有代码的潜在问题可能加重异常,优化后代码如下:
const options = { method: 'GET', headers: { "Authorization": `Bearer ${user?.token}` }, mode: 'cors', // 显式指定跨域模式,避免浏览器默认行为异常 }; // 对文件路径做转义处理,避免中文、特殊字符导致请求异常 fetch(`http://localhost:8080/storage/download?fileName=${encodeURIComponent(filePath)}`, options) .then(function (response) { return response.blob(); }) .then(function (myBlob) { setSpinControl(false); const file = new Blob([myBlob], { type: 'application/pdf' }); const fileURL = URL.createObjectURL(file); if (window) { // 用a标签触发下载,避免window.open被浏览器拦截 const downloadLink = document.createElement('a'); downloadLink.href = fileURL; downloadLink.download = filePath; document.body.appendChild(downloadLink); downloadLink.click(); document.body.removeChild(downloadLink); URL.revokeObjectURL(fileURL); // 手动释放内存,避免多次下载后内存溢出 } }) .catch((err) => { setSpinControl(false); console.log(err) });
4. 辅助排查手段
如果以上方案仍然无法解决,可通过以下方式定位具体问题:
- 打开浏览器控制台的「保留日志」选项,查看失败的请求是否为OPTIONS预检请求返回了403/400状态码
- 用curl命令模拟OPTIONS请求,检查后端返回的响应头是否符合预期:
curl -X OPTIONS -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: Authorization" -H "Origin: 你的前端服务地址" http://localhost:8080/storage/download?fileName=测试文件.pdf -v
内容的提问来源于stack exchange,提问作者RAFAEL DA SILVA
相关产品推荐
相关产品推荐

