createProductMedia results in "Media failed to process because the image could not be processed"

Viglucci
Shopify Partner
3 0 1

I am following a number of resources on the Shopify documentation website and blog around using the `stagedUploadsCreate` mutation to create a staged URL, however, once I try and use the staged resource URL in a later `productCreateMedia` mutation, the image is not attached to the product.

 

Docs: https://shopify.dev/api/examples/product-media


I suspect that there may be an issue with the S3 object being uploaded as private. If I manually try to visit the S3 object URL represented by `resourceUrl`, I receive an "access denied" response. I suspect that this may be resulting in the Shopify backend being unable to request the file during the `productCreateMedia` mutation as well. The strange thing is that `productCreateMedia` does not return any errors, the errors only show on the Shopify admin dashboard. Example below.

 

Screenshot_1.png

Is the URL given to `productCreateMedia` supposed to be a signed S3 object URL? If so, how would you produce such a URL?

I did notice that when using `PUT` for the `httpMethod` for `stagedUploadsCreate`, the uploadUrl seems to come back as signed or with additional query params, however when using `POST` that is not the case.

Example Code (stagedUploadsCreate)

 

 

const input = [
  {
    fileSize: file.size.toString(),
    filename: file.originalname,
    httpMethod: "POST",
    mimeType: file.mimetype,
    resource: "IMAGE",
  }
];

const {body} = await client.query({
  data: {
    query: `
      mutation stagedUploadsCreate($input: [StagedUploadInput!]!) {
        stagedUploadsCreate(input: $input) {
          stagedTargets {
            resourceUrl
            url
            parameters {
              name
              value
            }
          }
          userErrors {
            field
            message
          }
        }
      }
    `,
    variables: {
      input
    }
  }
});

 

 

 

Example Code (upload):

 

 

import fetch, {FormData} from 'node-fetch'

const formData = new FormData();

parameters.forEach(({name: paramName, value}) => {
  formData.append(paramName, value)
});
formData.append('file', file.buffer, {
  contentType: file.mimetype,
  filename: file.originalname
});

const response = await fetch(uploadUrl, {
  method: 'POST',
  body: formData
});

 

 

 

Example Code (productCreateMedia):

 

 

const variables = {
  id: productId,
  media: [
    {
      originalSource: resourceUrl,
      mediaContentType: "IMAGE"
    }
  ]
};

const {body} = await client.query({
  data: {
    query: `
        mutation createProductMedia(
          $id: ID!
          $media: [CreateMediaInput!]!
        ) {
          productCreateMedia(productId: $id, media: $media) {
            media {
              mediaContentType
              preview {
                image {
                  id
                }
              }
              mediaErrors {
                code
                details
                message
              }
              mediaWarnings {
                code
                message
              }
            }
            product {
              id
            }
            mediaUserErrors {
              code
              field
              message
            }
          }
        }
    `,
    variables
  }
});

 

 

Reply 1 (1)

Viglucci
Shopify Partner
3 0 1

I ultimately found the solution by reading this post: https://community.shopify.com/c/shopify-apis-and-sdks/full-process-for-uploading-files-to-the-files-...

My issue was that I was not passing the required headers for the request to upload the file to the AWS staging URL. Once I add the headers from `formData.getHeaders()`, the Shopify backend was then able to retrieve the image data and upload it to my product.