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

Uppy向S3上传错误图片问题排查求助

问题分析

你遇到的核心问题是更换图片时,旧图片会重新上传覆盖新图,结合代码来看,主要根源有以下几点:

  1. 重复上传逻辑冲突:Uppy的AwsAmplify插件本身已负责将文件上传到S3,但你又在complete事件中手动调用Storage.put,导致两次上传操作。若Uppy文件列表在上传过程中被旧文件干扰,就会出现旧图覆盖新图的情况。
  2. 事件处理依赖缺失:complete事件处理函数依赖data.id和editMode,但未将这两个变量加入useEffect的依赖数组,可能导致处理函数使用旧的变量值引发错误。
  3. 初始化逻辑重复触发:useLayoutEffect在isExpanded状态变化时,会重复将旧图片添加到Uppy实例中,触发不必要的上传操作。

解决方案

1. 移除冗余的手动上传逻辑

AwsAmplify插件已经完成S3上传工作,无需在complete事件中再次调用Storage.put,删除该部分代码:

useEffect(() => {
  const handleUploadError = (file, error, response) => {
    console.error("Upload error:", error, response);
  };

  const handleComplete = async (result) => {
    try {
      if (editMode) {
        console.log("Upload completed for entry:", data.id);
        console.log("Successfully uploaded files:", result.successful);
        // 可选:上传完成后清空Uppy文件列表,避免残留旧文件
        uppy.removeAllFiles();
        // 这里可以添加图片更新后的状态刷新逻辑(比如通知父组件重新获取图片)
      }
    } catch (e) {
      console.error(e);
    }
  };

  uppy.on("upload-error", handleUploadError);
  uppy.on("complete", handleComplete);

  return () => {
    // 移除指定的事件处理函数,避免内存泄漏
    uppy.off("upload-error", handleUploadError);
    uppy.off("complete", handleComplete);
  };
}, [uppy, data.id, editMode]); // 补充缺失的依赖项

2. 优化Uppy实例的AwsAmplify配置

确保插件配置与手动上传的参数一致(比如添加level: "public"),避免上传路径不一致:

const uppy = new Uppy({
  restrictions: {
    maxFileSize: 500000000,
    maxNumberOfFiles: 1,
    minNumberOfFiles: 1,
    allowedFileTypes: ["image/*"],
    debug: true,
  },
})
.use(ThumbnailGenerator, {
  thumbnailWidth: 300,
})
.use(AwsAmplify, {
  storage: Storage,
  limit: 50,
  id: data.id,
  putOptions: {
    bucket: "bucket-name",
    level: "public", // 与手动上传的level保持一致
  },
  getOptions: {
    download: false,
    bucket: "bucket-name",
    level: "public",
  },
});

3. 限制旧图片初始化逻辑的执行次数

添加状态标记,确保旧图片仅在组件首次加载时添加到Uppy,避免重复触发:

const [isInitialLoaded, setIsInitialLoaded] = useState(false);

useLayoutEffect(() => {
  const setImage = async () => {
    // 仅在首次加载、展开状态、编辑模式且Uppy无文件时执行
    if (isExpanded && uppy.getFiles().length === 0 && editMode && !isInitialLoaded) {
      try {
        const { ContentType, Body } = await Storage.get(data.id, {
          bucket: "bucket-name",
          level: "public",
          download: true,
        });
        const fileID = uppy.addFile({
          name: `${data.id}.${ContentType.split('/')[1]}`, // 给文件设置合理名称
          type: ContentType,
          data: Body,
          source: "Local",
          isRemote: false,
        });

        const uppyFile = uppy.getFile(fileID);
        // 模拟上传事件仅用于更新UI状态,无需实际上传
        uppy.emit("upload-started", uppyFile);
        uppy.emit("upload-progress", uppyFile, {
          bytesUploaded: Body.size,
          bytesTotal: Body.size,
        });
        uppy.emit("upload-success", uppyFile, "success");
        setIsInitialLoaded(true); // 标记已完成初始化
      } catch (err) {
        console.error("Failed to load existing image:", err);
      }
    }
  };
  setImage();
}, [isExpanded, data.id, uppy, editMode, isInitialLoaded]);

内容的提问来源于stack exchange,提问作者Ray Babich

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 14:55:58