如何在后端shopify应用程序上上传图片

问题描述 投票:0回答:1

我有 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>
  );
};
shopify shopify-app shopify-api
1个回答
0
投票

    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');
});

© www.soinside.com 2019 - 2024. All rights reserved.