Uppy向S3上传错误图片问题排查求助
问题分析
你遇到的核心问题是更换图片时,旧图片会重新上传覆盖新图,结合代码来看,主要根源有以下几点:
- 重复上传逻辑冲突:Uppy的
AwsAmplify插件本身已负责将文件上传到S3,但你又在complete事件中手动调用Storage.put,导致两次上传操作。若Uppy文件列表在上传过程中被旧文件干扰,就会出现旧图覆盖新图的情况。 - 事件处理依赖缺失:
complete事件处理函数依赖data.id和editMode,但未将这两个变量加入useEffect的依赖数组,可能导致处理函数使用旧的变量值引发错误。 - 初始化逻辑重复触发:
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
相关产品推荐
相关产品推荐

