Upload File pdf API

Hi all. I’m using a Custom Data field to allow to upload a PDF file each product on their Shopify store. The file is going to be downloadable from each product page.

I would like to write a function in C# to upload files via the API but I can’t understand what the correct procedure is.

This is my code example (it doesn’t work):

        public async Task UploadFile(byte[] fileContent, string fileName)
        {
            using (var client = new HttpClient())
            {
                var requestUri = $"https://{_shopifyStoreUrl}/admin/api/2023-10/files.json";
                client.DefaultRequestHeaders.Add("X-Shopify-Access-Token", _accessToken);

                var content = new MultipartFormDataContent();
                var fileContentContent = new ByteArrayContent(fileContent);
                fileContentContent.Headers.ContentDisposition = new ContentDispositionHeaderValue("form-data")
                {
                    Name = "\"file\"",
                    FileName = $"\"{fileName}\""
                };
                content.Add(fileContentContent);

                var response = await client.PostAsync(requestUri, content);
                response.EnsureSuccessStatusCode();
            }
        }

Can you help me understand where I’m wrong?

The response is: “StatusCode: 406, ReasonPhrase: ‘Not Acceptable’”

Thanks a lot.

Hey @MarcoIngShop ,

I can’t speak to the C# code specifically but can point you in the right direction. I don’t think there’s a /files endpoint - but you should be able to create a file with this (GraphQL) mutation.

Thank you for your suggestion. I understood that the operation must be done in 2 steps.

The first is GenerateUploadUrl and then upload.

I think I managed to do the first step but then it fails when I send the file.

I have upload url and parameters.

Could you help me understand where the error is in the second step?

This is my code:

public async Task

Hey @MarcoIngShop

Are you able to capture the request ID from the respond headers? This will let me examine the logs.

X-GUploader-UploadID → ABPtcPqz1u45k2z5XfYw5nAdUtiIcSiOMp3mvHZ8spxt2_MB3PlIus6aMscZ73SIoVfc_tA1kxcXZCt7oQ

I thik that this is the point “critical”.

I would like to understand if I have to make a put or a post and if the parameters I send are correct (if they go in the header or in the body).

//Load File
            var formContent = new MultipartFormDataContent();
            foreach (var parameter in uploadParameters)
            {
                formContent.Add(new StringContent(parameter["value"]), parameter["name"]);
            }
            string base64String = Convert.ToBase64String(fileContent);
            formContent.Add(new StringContent(base64String),"data");
            formContent.Add(new StringContent(fileName), "filename");
            //formContent.Add(new ByteArrayContent(fileContent), "data", fileName);
            //formContent.Add(new ByteArrayContent(fileContent),"data");
            //HttpContent httpContent = new HttpContent();

                      
            var uploadResult = await _httpClient.PostAsync(uploadUrl, formContent);
            if (!uploadResult.IsSuccessStatusCode)
            {
                throw new Exception("Failed to upload file.");
            }

I can’t speak to the code directly, but this article breaks down the steps - maybe try running through this first: https://shopify.dev/docs/apps/online-store/media/products#generate-the-upload-url-and-parameters

It’s specifically for product media, so difference would be:

  • you would specify FILE for the StagedUploadTargetGenerateUploadResource

  • after uploading the file, you can add the file to the Files page in Shopify admin using the fileCreate mutation.

Hi,
This article is missing the example in “UPLOAD SECTION” of when a generic “FILE” type must be uploaded (in my case a PDF) so I can’t understand if the request must be of type POST or PUT and where (and how) the parameters should be passed.

Can you tell me if for a generic FILE (pdf) type the request must be POST OR PUT and how the parameters should be passed?

In the first step I followed the instructions by putting the type “FILE” and I received the correct parameters but when it says to upload I tried various ways without success.

Thanks a lot.

Can you check the log for this request:

X-GUploader-UploadID: ABPtcPqgQzIR9moKLvUInt0f35gTM7dK1NMGRDfIT2mEa1iEyUaGLDWVfniZHVTqTIeasppOz0s
Date: Thu, 23 Nov 2023 20:26:05 GMT
Server: UploadServer
Alt-Svc: h3=“:443”; ma=2592000
Alt-Svc: h3-29=“:443”; ma=2592000
Content-Type: text/plain; charset=utf-8
Content-Length: 25

Thanks a lot.

Hey @MarcoIngShop

Just tried it out - we could use better docs on the process :sweat_smile: I had success with the following method:

  1. Generate a staged upload URL
mutation generateStagedUploads {
  stagedUploadsCreate(input: [
    {
      filename: "example.pdf",
      mimeType: "application/pdf",
      resource: FILE
    }
  ])
    {
    stagedTargets {
      url
      resourceUrl
      parameters {
        name
        value
      }
    }
    userErrors {
      field, message
    }
  }
}
  1. Upload the file (A PUT request to data.stagedUploadsCreate.stagedTargets.url from step 1. If you want to test in Postman here’s an example screenshot.

  2. If you get a 200 OK from step 2, then you can use the fileCreate mutation to add the file to the ‘files’ section of the admin. You only need to pass the originalSource param, which is the data.stagedUploadsCreate.stagedTargets.url value from step one without any of the params.

{
  "files": [
    {
      "originalSource": "https://shopify-staged-uploads.storage.googleapis.com/tmp/.../example.pdf"
    }
  ]
}

Let me know how you go!