向Firebase Storage传文件时JS报Failed to fetch错误求助
问题诊断与修复方案
一、前端代码核心问题
1. 请求头拼写错误 + 无效请求头
你的fetch配置里写的是header,正确字段名是headers;另外Access-Control-Allow-Origin是后端返回给前端的响应头,前端请求时添加这个头完全无效,反而可能触发浏览器CORS校验异常。
修复后的fetch配置:
fetch("http://localhost:8080/images/incidents/pics", { method: "POST", body: formData, // 移除无效请求头,formData请求的Content-Type会由浏览器自动处理 })
2. 重复绑定点击事件
每次文件选择(change事件触发)都会执行handleImageUpload,而方法内又给按钮绑定一次click事件,导致点击按钮时触发多次请求,引发不可预料的错误。
修复:将点击事件绑定移到外部,避免重复绑定:
const fileUploadButton = document.getElementById("fileUploadButton"); let selectedFiles; // 全局变量存储选中的文件 // 仅监听文件选择事件,存储文件 document.querySelector("#fileUpload").addEventListener("change", (event) => { selectedFiles = event.target.files; }); // 单独绑定按钮点击事件,处理上传 fileUploadButton.addEventListener('click',function(e){ e.preventDefault(); if (!selectedFiles || selectedFiles.length === 0) { console.log("请先选择文件"); return; } const formData = new FormData(); for (const file of selectedFiles) { formData.append("files", file); } fetch("http://localhost:8080/images/incidents/pics", { method: "POST", body: formData, }) .then((response) => { // 先校验响应状态,非2xx状态直接抛出错误 if (!response.ok) { throw new Error(`请求失败,状态码:${response.status}`); } return response.json(); }) .then((data) => { console.log(data); sessionStorage.setItem("incidents_photo_paths", JSON.stringify(data)); }) .catch((error) => { console.error("上传错误:", error); }); })
3. then链逻辑错误
原代码中then((data) => (res = data))无返回值,导致后续then拿到undefined;且res未声明,属于全局变量污染。直接在拿到响应数据后处理sessionStorage即可,无需额外then步骤。
二、后端Spring Service逻辑错误
你的uploadMultipleFiles方法里,循环处理时每次都取multipartFileList的最后一个文件(multipartFileList.get(multipartFileList.size()-1)),还重复调用convertToFile生成冗余临时文件。虽然文件能上传,但逻辑错误会导致异常捕获后返回错误响应,前端解析json时触发报错。
修复循环逻辑,正确匹配每个文件:
public ListResponse uploadMultipleFiles(List<MultipartFile> multipartFileList) { List<String> tempUrlList = new ArrayList<>(); try { for (MultipartFile multipartFile : multipartFileList) { String originalFileName = multipartFile.getOriginalFilename(); String fileName = UUID.randomUUID().toString().concat(this.getExtension(originalFileName)); File file = this.convertToFile(multipartFile, fileName); tempUrlList.add(this.uploadFile(file, fileName)); file.delete(); } return new ListResponse(tempUrlList); } catch (Exception e) { e.printStackTrace(); return new ListResponse("Error, could not upload!"); } }
同时可删除无用的fileNameList和fileList变量,简化逻辑。
三、额外注意事项
- 确保后端Spring控制器已配置CORS,比如添加
@CrossOrigin注解或全局CORS配置,否则即使文件上传成功,前端仍会因CORS限制抛出fetch错误。 - 临时文件优化:
convertToFile方法中,new File(fileName)会在项目根目录生成文件,建议使用系统临时目录避免权限问题:
File tempFile = File.createTempFile(UUID.randomUUID().toString(), getExtension(fileName));
内容的提问来源于stack exchange,提问作者Vlad1791
相关产品推荐
相关产品推荐

