Shopify后端图片上传异常:状态停滞上传中,求解决方案
Shopify图片上传卡在Uploading状态的解决方案
你的代码存在三个核心问题,导致上传后后台显示失败、状态无法从Uploading推进到Processing/Ready:
1. 跳过了实际文件上传到Staged Target的关键步骤
调用stagedUploadsCreate仅获取了Shopify提供的临时上传地址,但未将本地文件的二进制内容POST到该地址。Shopify未收到文件实体,自然会一直卡在Uploading状态,最终标记上传失败。
2. fileCreate的变量格式错误
你传入的files是单个对象,但GraphQL接口要求该参数为数组类型,格式不匹配会导致文件创建逻辑异常。
3. 前端未提交实际文件内容
当前前端仅提交了文件名、类型、大小等元数据,后端无法获取到要上传的文件二进制数据,根本无法完成实际上传操作。
具体修复步骤
步骤1:前端修改提交逻辑,传递实际文件
更新generateProduct方法,用FormData封装文件实体后提交:
const generateProduct = () => { if (!files[0]) return; const formData = new FormData(); formData.append("file", files[0]); formData.append("filename", files[0].name); formData.append("filetype", files[0].type); formData.append("filesize", files[0].size.toString()); submit(formData, { replace: true, method: "POST" }); };
步骤2:后端处理FormData,完成文件上传到Staged Target
修改action函数,先解析FormData拿到文件,再将文件POST到Staged Target地址,最后修复fileCreate的参数格式:
export const action = async ({ request }: ActionFunctionArgs) => { const { admin } = await authenticate.admin(request); // 解析FormData获取实际文件 const formData = await request.formData(); const file = formData.get("file") as File; const name = formData.get("filename") as string; const type = formData.get("filetype") as string; const size = formData.get("filesize") as string; const prepareFiles = (files: { name: string; type: string; size: string; }[]) => files.map((file) => ({ filename: file.name, mimeType: file.type, resource: file.type.includes("image") ? "IMAGE" : "FILE", fileSize: file.size, httpMethod: "POST", })); const preparedFiles = prepareFiles([{ name, type, size }]); // 1. 获取Staged Upload目标地址 const uploadFileResponse = await admin.graphql( `#graphql mutation stagedUploadsCreate($input: [StagedUploadInput!]!) { stagedUploadsCreate(input: $input) { stagedTargets { resourceUrl url parameters { name value } } userErrors { field message } } } `, { variables: { input: preparedFiles } }, ); const uploadFileJson = await uploadFileResponse.json(); const stagedTarget = uploadFileJson.data.stagedUploadsCreate.stagedTargets[0]; // 检查Staged Upload是否存在错误 if (uploadFileJson.data.stagedUploadsCreate.userErrors.length > 0) { return json({ error: uploadFileJson.data.stagedUploadsCreate.userErrors }); } // 2. 关键操作:将文件上传到Staged Target的URL const uploadForm = new FormData(); // 添加Staged Target返回的参数 stagedTarget.parameters.forEach(param => { uploadForm.append(param.name, param.value); }); // 添加文件实体 uploadForm.append("file", file); await fetch(stagedTarget.url, { method: "POST", body: uploadForm, }); // 3. 修复fileCreate参数格式:files改为数组 const fileCreateResponse = await admin.graphql( `#graphql mutation fileCreate($files: [FileCreateInput!]!) { fileCreate(files: $files) { files { alt createdAt fileStatus fileErrors { code details message } preview { image { url } status __typename } ... on GenericFile { id } ... on Video { id } } userErrors { code field message } } }`, { variables: { files: [{ alt: "Image", contentType: "IMAGE", originalSource: stagedTarget.resourceUrl, }], }, }, ); const fileCreateJson = await fileCreateResponse.json(); // 检查fileCreate是否存在错误 if (fileCreateJson.data.fileCreate.userErrors.length > 0) { return json({ error: fileCreateJson.data.fileCreate.userErrors }); } return json({ stagedUpload: uploadFileJson, fileCreate: fileCreateJson, resourceurl: stagedTarget.resourceUrl }); };
步骤3:添加错误提示逻辑
更新前端useEffect,根据返回结果显示成功/失败提示:
useEffect(() => { if (actionData) { if (actionData.error) { shopify.toast.show(`上传失败: ${actionData.error.map(e => e.message).join(", ")}`); } else { shopify.toast.show("图片上传成功"); } } }, [actionData]);
额外排查建议
- 上传后打印
fileCreateJson.data.fileCreate.files[0].fileErrors,可获取具体的文件错误信息,辅助排查问题。 - 如需支持多文件上传,需循环处理每个文件的Staged Upload和实体上传步骤。
- 可添加文件上传进度监听,提升用户体验。
内容的提问来源于stack exchange,提问作者mohit vamja
相关产品推荐
相关产品推荐

