我有 Shopify 后端图像上传的代码。我的代码图像上传成功消息,但当我转到后端媒体文件内容时,显示错误消息“5 个文件失败”。我将分享我的代码,我的代码正在运行,但图像状态显示正在上传。这在处理和就绪状态下不起作用。所以请给出正确的解决方案。我将分享一些屏幕截图。
import React, { useCallback, useEffect, useState, useRef } from "react";
import { json } from "@remix-run/node";
import { useActionData, useNavigation, useSubmit } from "@remix-run/react";
import {
Page,
Layout,
Card,
Button,
BlockStack,
Box,
InlineStack,
DropZone,
LegacyStack,
Thumbnail,
Text,
} from "@shopify/polaris";
import { authenticate } from "../shopify.server";
import type { ActionFunctionArgs, LoaderFunctionArgs } from "@remix-run/node";
export const loader = async ({ request }: LoaderFunctionArgs) => {
await authenticate.admin(request);
return null;
};
export const action = async ({ request }: ActionFunctionArgs) => {
const { admin } = await authenticate.admin(request);
const color = ["Red", "Orange", "Yellow", "Green"][
Math.floor(Math.random() * 4)
];
const requestBody = await request.text();
const formData = new URLSearchParams(requestBody);
const name = formData.get("filename");
const type = formData.get("filetype");
const size = formData.get("filesize");
const files = [
{
name: name,
type: type,
size: size,
},
];
const prepareFiles = (files: { name: string | null; type: string | null; size: string | null; }[]) =>
files.map((file) => ({
filename: file.name,
mimeType: file.type,
resource: file.type?.includes("image") ? "IMAGE" : "FILE",
fileSize: file.size?.toString(),
httpMethod: "POST",
}));
const preparedFiles = prepareFiles(files);
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 uplodeFileJson = await uploadFileResponse.json();
const resourceurl = uplodeFileJson.data.stagedUploadsCreate.stagedTargets[0].resourceUrl;
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: resourceurl,
},
},
},
);
const fileCreateJson = await fileCreateResponse.json();
return ({
stagedUpload: uplodeFileJson,
fileCreate: fileCreateJson,
resourceurl: resourceurl
});
};
export default function Index() {
const nav = useNavigation();
const actionData = useActionData();
const submit = useSubmit();
const isLoading = ["loading", "submitting"].includes(nav.state) && nav.formMethod === "POST";
useEffect(() => {
if (actionData) {
shopify.toast.show("Product created");
}
}, [actionData]);
const [files, setFiles] = useState<File[]>([]);
const inputRef = useRef<HTMLInputElement>(null);
const handleDropZoneDrop = useCallback(
async (dropFiles: File[], acceptedFiles: File[], rejectedFiles: File[]) => {
if (acceptedFiles.length) {
setFiles((prevFiles) => [...prevFiles, ...acceptedFiles]);
for (const file of acceptedFiles) {
console.log(file.name);
console.log(file.size);
console.log(file.type);
}
}
},
[],
);
const validImageTypes = ["image/gif", "image/jpeg", "image/png"];
const fileUpload = !files.length && <DropZone.FileUpload />;
const uploadedFiles = files.length > 0 && (
<div style={{ padding: "0" }}>
<LegacyStack vertical>
{files.map((file, index) => (
<LegacyStack alignment="center" key={index}>
<Thumbnail
size="small"
alt={file.name}
source={
validImageTypes.includes(file.type)
? window.URL.createObjectURL(file)
: ""
}
/>
<div>
{file.name}{" "}
<Text variant="bodySm" as="p">
{file.size} bytes
</Text>
</div>
</LegacyStack>
))}
</LegacyStack>
</div>
);
const generateProduct = () => {
const filename = files[0]?.name;
const filetype = files[0]?.type;
const filesize = files[0]?.size;
submit({ filename, filetype, filesize }, { replace: true, method: "POST" });
};
return (
<Page>
<BlockStack gap="500">
<Layout>
<Layout.Section>
<Card>
<InlineStack gap="300">
<DropZone onDrop={handleDropZoneDrop}>
{uploadedFiles}
{fileUpload}
</DropZone>
<Button loading={isLoading} onClick={generateProduct}>
Generate a product
</Button>
</InlineStack>
</Card>
</Layout.Section>
</Layout>
</BlockStack>
</Page>
);
};
const express = require('express');
const multer = require('multer'); // For handling file uploads
const Shopify = require('shopify-api-node'); // Shopify API client library
const app = express();
const upload = multer({ dest: 'uploads/' }); // Destination folder for uploaded files
// Initialize Shopify API client
const shopify = new Shopify({
shopName: 'your-shop-name',
apiKey: 'your-api-key',
password: 'your-api-password',
});
// Route for handling image upload
app.post('/upload-image', upload.single('image'), (req, res) => {
// Handle image processing, validation, etc.
const imageFile = req.file; // The uploaded image file
// Upload the image to Shopify
shopify.asset.create({
key: 'uploads/' + imageFile.filename, // File path on Shopify (you may need to adjust this)
src: imageFile.path, // Local path of the uploaded image file
})
.then(asset => {
// Image uploaded successfully
res.json({ success: true, asset });
})
.catch(error => {
// Error occurred during image upload
console.error('Error uploading image to Shopify:', error);
res.status(500).json({ success: false, error: 'Image upload failed' });
});
});
// Start the server
app.listen(3000, () => {
console.log('Server is running on port 3000');
});