通过 API 上传产品图片 - 尽管状态为 200 无法弄清楚,但图片未出现

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

我遇到一个问题,即通过 Shopify 管理 API 上传产品图片返回 200 OK 状态代码,表示成功,但图片实际上并未附加到产品。

这是我观察到的:

  1. 上传图片的 API 请求始终返回 200 OK 状态代码。
  2. 响应负载不包含任何错误消息。 图片上传后不会触发“产品/更新”主题的 Webhook。

我已尝试以下故障排除步骤:

  1. 上传不同的图像(各种尺寸、格式)。
  2. 从图像上传负载中删除元字段。
  3. 上传后等待较长时间。
  4. 检查 Shopify 状态页面是否存在已知问题。
  5. 添加webhook并登录webhook(产品更新)但没有请求webhook!

要求以下内容:

  1. Shopify API 版本:2024-04
  2. 产品编号:9330543722782

您能进一步调查这个问题并帮我解决吗?

这里。我的代码

    import dotenv from 'dotenv';
dotenv.config();
import fetch from 'node-fetch';
import fs from 'fs';
const LATEST_API_VERSION = '2024-04';

async function uploadImage(imagePath) {
    const product_id = 9330543722782;
    try {
        const imageData = fs.readFileSync(imagePath);
        const base64Image = imageData.toString('base64');

        const timestamp = Date.now();
        const filename = `image-${timestamp}.png`;

        const imagePayload = {
            image: {
                product_id: product_id,
                position: timestamp,
                metafields: [
                    {
                        key: "upload_timestamp",
                        value: `${timestamp}`,
                        type: "single_line_text_field",
                        namespace: "global"
                    }
                ],
                attachment: base64Image,
                filename: filename
            }
        };

        const response = await fetch(`https://${process.env.SHOPIFY_SHOP}/admin/api/${LATEST_API_VERSION}/products/${product_id}/images.json`, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-Shopify-Access-Token': process.env.SHOPIFY_ACCESS_TOKEN
            },
            body: JSON.stringify(imagePayload)
        });

        if (!response.ok) {
            const errorData = await response.json(); 
            throw new Error(`Image upload failed: ${response.statusText} - ${JSON.stringify(errorData)}`);
        }
        const statusCode = response.status;
        console.log ("Status Code", statusCode);
        const responseData = await response.json();
        console.log ("Response Data", responseData);
        console.log("Full Response:", response); 

        return "";

    } catch (error) {
        console.error('Error uploading image:', error.message);
        throw error; 
    }
}

async function listProducts() {
    try {
      const response = await fetch(
        `https://${process.env.SHOPIFY_SHOP}/admin/api/${LATEST_API_VERSION}/products.json`,
        {
          method: 'GET',
          headers: {
            'Content-Type': 'application/json',
            'X-Shopify-Access-Token': process.env.SHOPIFY_ACCESS_TOKEN,
          },
        }
      );
  
      if (!response.ok) {
        const errorData = await response.json();
        throw new Error(
          `Failed to list products: ${response.statusText} - ${JSON.stringify(errorData)}`
        );
      }
  
      const data = await response.json();
      return data.products; 
    } catch (error) {
      console.error('Error listing products:', error.message);
      throw error; 
    }
  }

export { uploadImage, listProducts };

使用方法

import { uploadImage, listProducts } from './helper/shopify.js';
// const { logger } = from './helper/log';

(async () => {
    let products = await listProducts();
    console.log("Products:", products);
    let imagePath = "./tmp/test.png";
    let url = await uploadImage(imagePath);
    console.log("Image uploaded successfully. URL:", url);
})();

日志:

node test.js  
Products: [
  {
    id: 9330543722782,
    title: 'Hidden product',
    body_html: '<p>name</p>\n<!---->',
    vendor: 'My Store',
    product_type: '',
    created_at: '2024-05-26T08:45:27+05:00',
    handle: 'hidden-product',
    updated_at: '2024-05-26T08:50:13+05:00',
    published_at: '2024-05-26T08:46:17+05:00',
    template_suffix: '',
    published_scope: 'global',
    tags: '',
    status: 'active',
    admin_graphql_api_id: 'gid://shopify/Product/9330543722782',
    variants: [ [Object] ],
    options: [ [Object] ],
    images: [],
    image: null
  }
]
Status Code 200
Response Data { images: [] }
Full Response: Response {
  size: 0,
  [Symbol(Body internals)]: {
    body: Gunzip {
      _writeState: [Uint32Array],
      _events: [Object],
      _readableState: [ReadableState],
      _writableState: [WritableState],
      allowHalfOpen: true,
      _maxListeners: undefined,
      _eventsCount: 6,
      bytesWritten: 33,
      _handle: null,
      _outBuffer: <Buffer 7b 22 69 6d 61 67 65 73 22 3a 5b 5d 7d 00 00 00 00 00 00 00 00 00 00 00 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 16334 more bytes>,
      _outOffset: 13,
      _chunkSize: 16384,
      _defaultFlushFlag: 2,
      _finishFlushFlag: 2,
      _defaultFullFlushFlag: 3,
      _info: undefined,
      _maxOutputLength: 4294967296,
      _level: -1,
      _strategy: 0,
      [Symbol(shapeMode)]: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: null,
      [Symbol(kError)]: null
    },
    stream: Gunzip {
      _writeState: [Uint32Array],
      _events: [Object],
      _readableState: [ReadableState],
      _writableState: [WritableState],
      allowHalfOpen: true,
      _maxListeners: undefined,
      _eventsCount: 6,
      bytesWritten: 33,
      _handle: null,
      _outBuffer: <Buffer 7b 22 69 6d 61 67 65 73 22 3a 5b 5d 7d 00 00 00 00 00 00 00 00 00 00 00 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ... 16334 more bytes>,
      _outOffset: 13,
      _chunkSize: 16384,
      _defaultFlushFlag: 2,
      _finishFlushFlag: 2,
      _defaultFullFlushFlag: 3,
      _info: undefined,
      _maxOutputLength: 4294967296,
      _level: -1,
      _strategy: 0,
      [Symbol(shapeMode)]: true,
      [Symbol(kCapture)]: false,
      [Symbol(kCallback)]: null,
      [Symbol(kError)]: null
    },
    boundary: null,
    disturbed: true,
    error: null
  },
  [Symbol(Response internals)]: {
    type: 'default',
    url: 'https://3bcfc2-81.myshopify.com/admin/api/2024-04/products/9330543722782/images.json',
    status: 200,
    statusText: 'OK',
    headers: {
      'alt-svc': 'h3=":443"; ma=86400',
      'cf-cache-status': 'DYNAMIC',
      'cf-ray': '889b1faa6c066032-SIN',
      connection: 'keep-alive',
      'content-encoding': 'gzip',
      'content-security-policy': "default-src 'self' data: blob: 'unsafe-inline' 'unsafe-eval' https://* shopify-pos://*; block-all-mixed-content; child-src 'self' https://* shopify-pos://*; connect-src 'self' wss://* https://*; frame-ancestors 'none'; img-src 'self' data: blob: https:; script-src https://cdn.shopify.com https://cdn.shopifycdn.net https://checkout.shopifycs.com https://api.stripe.com https://mpsnare.iesnare.com https://appcenter.intuit.com https://www.paypal.com https://js.braintreegateway.com https://c.paypal.com https://maps.googleapis.com https://www.google-analytics.com https://v.shopify.com 'self' 'unsafe-inline' 'unsafe-eval'; upgrade-insecure-requests; report-uri /csp-report?source%5Baction%5D=index&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Fproduct_images&source%5Bsection%5D=admin_api&source%5Buuid%5D=0058cebc-6004-44ff-b39c-b4b06ccc228f-1716698809",
      'content-type': 'application/json; charset=utf-8',
      date: 'Sun, 26 May 2024 04:46:50 GMT',
      http_x_shopify_shop_api_call_limit: '1/40',
      nel: '{"success_fraction":0.01,"report_to":"cf-nel","max_age":604800}',
      'referrer-policy': 'origin-when-cross-origin',
      'report-to': '{"endpoints":[{"url":"https:\\/\\/a.nel.cloudflare.com\\/report\\/v4?s=SW3LirD9f%2Bp2E2u4QrazyqQDfMeFsZA%2FzOaPGjs0O4w91%2FH8BlCH%2FC53BzHokV7b7LjSaIaEL5KDqae6nWrmifnN6SF%2BGA0%2FxOfVpc9nzm5xkh5%2BJ%2BAaEPOTmoAAs9EauDjxQk4feNQH"}],"group":"cf-nel","max_age":604800}',
      server: 'cloudflare',
      'server-timing': [Array],
      'transfer-encoding': 'chunked',
      vary: 'Accept-Encoding',
      'x-content-type-options': 'nosniff',
      'x-dc': 'gcp-asia-southeast1,gcp-us-central1,gcp-us-central1',
      'x-download-options': 'noopen',
      'x-frame-options': 'DENY',
      'x-permitted-cross-domain-policies': 'none',
      'x-request-id': '0058cebc-6004-44ff-b39c-b4b06ccc228f-1716698809',
      'x-shardid': '285',
      'x-shopid': '87735271710',
      'x-shopify-api-version': '2024-04',
      'x-shopify-shop-api-call-limit': '1/40',
      'x-sorting-hat-podid': '285',
      'x-sorting-hat-shopid': '87735271710',
      'x-stats-apiclientid': '123940864001',
      'x-stats-apipermissionid': '711507738910',
      'x-stats-userid': '',
      'x-xss-protection': '1; mode=block; report=/xss-report?source%5Baction%5D=index&source%5Bapp%5D=Shopify&source%5Bcontroller%5D=admin%2Fproduct_images&source%5Bsection%5D=admin_api&source%5Buuid%5D=0058cebc-6004-44ff-b39c-b4b06ccc228f-1716698809'
    },
    counter: 1,
    highWaterMark: 16384
  }
}
Image uploaded successfully. URL: 
shopify
1个回答
0
投票

您从

uploadImage()
返回一个空字符串,因此
let url = await uploadImage(imagePath);
肯定会返回一个空字符串。

因此,请务必返回您的回复。

此外,由于记录

responseData
显示空
images
数组,这意味着即使请求成功,实际上也没有上传任何图像。

所以,再看看你的

imagePayload

  • 检查
    imagePath
    是否是正确的文件路径
  • 确认图像被正确读取并且
    imageData
    实际上返回了正确的数据
  • 也确认编码
  • 验证您是否使用 Shopify API 有效负载所需的正确格式和字段
© www.soinside.com 2019 - 2024. All rights reserved.