You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

向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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 08:18:36