Uploading file problem

I have an api post endpoint that uses a csv file as input. I'm using a file button to upload the file, and then use it in the query as depicted in the screenshot attached. Although it does seem the file gets passed to the api, something goes wrong on the way, since it can't be parsed by the downstream code. Running the api from command line works fine.

Adding the command line call I would like to implement in Retool:

  curl -X 'POST' \
  'http://base_url/session-text/upload' \
  -H 'accept: application/json' \
  -H 'Authorization: Bearer longCode ' \
  -H 'Content-Type: multipart/form-data' \
  -F 'file=@file_name.csv;type=application/vnd.ms-excel'

Hey @Einat!

Can you try using {{ { data: fileButton1.value[0], ...fileButton1.files[0] } }} instead of {{ fileButton1.value[0] }} and see if that works correctly?

It doesn't work, I get the same error

You'll likely also need to remove the Content-Type header from the request. Retool will automatically add a content-type header and set it to multipart/form-data along with the boundary:

I'm interested to know what error you're getting as well, that may help with further debugging!

Removing the header did the trick, thanks!

This worked for me. Would you be able to share the document explaining how and why this works?

Hi @unknown! The multipart/form-data content type splits fields depending on the boundary that's defined in the request, there's a nice stackoverflow thread with a few explanations here. In short, the boundary should be something that doesn't appear anywhere in the data itself and gets defined as part of the content-type header.

When you choose Form Data as the Body type in Retool, it will automatically generate a boundary, include it in the header, and use it to demarcate fields in the data as part of formatting the request. If you choose to specify a content-type header in your request that can override the one generated by Retool meaning the boundary will be lost to the endpoint and it won't be able to parse the data correctly.

As far as the syntax for passing data goes, retool splits a file's metadata off into the files property so using {{ { data: fileButton1.value[0], ...fileButton1.files[0] } }} creates an object that contains both data and metadata for the upload. More about spread syntax here!

Let me know if that doesn't answer your questions! :slightly_smiling_face: