Uploading Images from Forms via Netlify Functions

Hi there. I’m building a directory site for an art collective using Gatsby, and want users to be able to apply to be listed from a form on the site.

I’ve enlisted the Content Management API to create the new Artist record upon completion of the form by putting it within a Netlify function, but hit a snag with uploading the submitted avatar image that is part of the form.

Does the client.uploadFile() method only accept a URL or relative path? I tried uploading a data url and keep getting a 500 error response. I’m not sure how to get this file to a place where it can be referenced by URL from a frontend form.

Thanks for your help, and apologies if I’ve missed something glaring, I’m new to this. First community forum post anywhere actually!

I’m trying out an additional option in case the data url route doesn’t work out.

I saw a guide on how to use the three step upload process directly here but the example call is only in HTTP, and reverts to the client.uploadFile() approach when I click the Javascript example tab.

I thought I had translated the example into a fetch() request correctly below:

const requestRes = await fetch(`https://site-api.datocms.com/upload-requests`, {
  method: 'POST',
  headers:  {
     'X-Api-Version': 3,
     'Authorization': `Bearer ${ process.env.DATO_CONTENT_TOKEN }`,
     'Accept': 'application/json',
     'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    type: "upload_request",
    attributes: {
      filename: "image.png"
    },
  }),
})

But I am getting the following response code and text (within the Response, the fetch itself responds with a 200 ok status): 422 Unprocessable Entity

Hello @frank.ringofkeys sorry for the delay here, still catching up from holidays :frowning:

client.uploadFile() is just some syntactic sugar on top of the three calls that we are doing. You can read more details here: https://github.com/datocms/js-datocms-client/blob/544b5b08ebddd5e3037749c1ecf096d6ce524a36/src/upload/adapters/browser.js for the browser implementation

We do a PUT on S3 of the asset after we have the path and then we create the upload object on Dato.

Let me know if you need more details here!

1 Like

Thanks @mat_jack1! Apologies I should have followed up.

Ah I understand now, I should have actually read the code in that repository, it came up in my Googling :sweat_smile:.

I think I was having trouble with clients.uploadFile() within my Netlify function but I’ll revisit.

If anyone has that struggle, I was able to do a slightly modified three-step upload process as follows:

  1. call client.uploadRequest.create() within a Netlify function (because it requires your token), passing in it your File object from the form.
  2. back on the client-side do a fetch PUT request to the returned url value from the above, using FileReader.readAsArrayBuffer() and JSON.stringify to put the contents of the file into the body of the request.
  3. pass the id property from step one to another Netlify function where you call client.uploads.create() followed by client.items.create()

I’m sure it’s entirely too much passing things around but it worked for me in a pinch.

1 Like

I think that’s perfect! Thank you for sharing that back!

1 Like