Uploading files using multipart form data

Hi all. I want to start off by saying that i am fairly new to robot framework. I have been using the following link as reference - Uploading files using multipart/form-data through REST API

However, i am having issues with sending multiple files this is due to the fact that the server expects the key as “data” and when i opt to do multiple files like this line:
&{enrol_data}= Create Dictionary
Set To Dictionary ${enrol_data} data=${partData1}
Set To Dictionary ${enrol_data} data=${partData2}

So i guess is there anyway to append the files, or put them into an array to easily send up the block of code for this is the following

Enrol User

Create Session    EnrolUserSession    ${base_url}
${enrol_url}    Set Variable    ${base_url}/test
${enrol_headers}    Create Dictionary       X-Session-ID=${sessionid}    X-Session-Token=${token}

${file_data1}=  Get Binary File  ${file_path}
${fileDir}  ${fileName}=  Split Path  ${file_path}
${partData1}=  Create List  ${fileName}  ${file_data1}  audio/x-wav
${file_data2}=  Get Binary File  ${file_path2}
${fileDir}  ${fileName}=  Split Path  ${file_path2}
${partData2}=  Create List  ${fileName}  ${file_data2}  audio/x-wav
Append To List  ${partData1}   ${partData2}
&{enrol_data}=   Create Dictionary 
Set To Dictionary  ${enrol_data}   data=${partData1}  
Set To Dictionary  ${enrol_data}   data=${partData2}

${enrol_response}    POST On Session    EnrolUserSession    ${enrol_url}       files=${enrol_data}   headers=${enrol_headers} 
Should Be Equal As Strings    ${enrol_response.status_code}    200

As i’m not really used to posting on these sort of forums, please let me know if i need to elaborate further many thanks.

Hi Luke,

If the server allows you to send multiple files then perhaps you need a list of dictionaries?

something like this:

@{enrol_list}=    Create List
&{enrol_data}=    Create Dictionary
Set To Dictionary    ${enrol_data}     data=${partData1}
Append To List    ${enrol_list}    ${enrol_data}
&{enrol_data}=    Create Dictionary
Set To Dictionary    ${enrol_data}     data=${partData2}
Append To List    ${enrol_list}    ${enrol_data}

# your other lined here

${enrol_response}    POST On Session    EnrolUserSession    ${enrol_url}       files=${enrol_list}   headers=${enrol_headers} 

It’s just a guess, I don’t know enough about your apps API to know if this is correct or not, howeverer this is the normal way to do it with JSON.

Dave.

Hi Dave,
Thank you for replying. For context this is the equivalent curl command which works on our API server.

curl -X 'POST' \
  'https://<serversurl> \
  -H 'accept: application/json' \
  -H 'X-Session-ID: ****' \
  -H 'X-Session-Token: ****' \
  -H 'Content-Type: multipart/form-data' \
  -F 'data=@Recording1.wav;type=audio/wav' \
  -F 'data=@Recording2.wav;type=audio/wav' \
  -F 'data=@Recording3.wav;type=audio/wav' \
  -F 'language=en' \
  -F 'profile=default' 

Hi Luke,

As far as I know requests library only does a single file as post data for you, so for something like this you’ll need to construct the request body yourself then send it with requests library.

I’d suggest you run curl with the -v or --verbose option so you can capture exactly what you need to reproduce, both headers and request body.

Using the example raw post data from here as an example, I expect you’ll need something like this:

headers:

POST /<path> HTTP/1.1
Host: https://<serversurl>
accept: application/json
X-Session-ID: ****
X-Session-Token: ****
Content-Length: <value you`ll need to calculate>
Content-Type: multipart/form-data; boundary=----<generated boundary value>

Request body:

----<generated boundary value>
Content-Disposition: form-data; name="data"; filename="Recording1.wav"
Content-Type: audio/wav

IHDRwSÞsRGB®ÎégAMA± üa	pHYsÃÃÇo¨dIDATWcøÿÿ?þþ§5IEND®B`
----<generated boundary value>
Content-Disposition: form-data; name="data"; filename="Recording2.wav"
Content-Type: audio/wav

IHDRwSÞsRGB®ÎégAMA± üa	pHYsÃÃÇo¨dIDATWcøÿÿ?þþ§5IEND®B`
----<generated boundary value>
Content-Disposition: form-data; name="data"; filename="Recording3.wav"
Content-Type: audio/wav

IHDRwSÞsRGB®ÎégAMA± üa	pHYsÃÃÇo¨dIDATWcøÿÿ?þþ§5IEND®B`
----<generated boundary value>
Content-Disposition: form-data; name="language"

en
----<generated boundary value>
Content-Disposition: form-data; name="profile"

default
----<generated boundary value>
  • the ${file_data1}= Get Binary File ${file_path} will probably be what you need for the file data parts
  • the file names you already know I guess
  • Generate Random String will probably be useful for generating a boundary value, I don’t think it matters what the boundary string is as long as it’s unique to this post request and consistent throughout the request

I’d try doing it in this order:

  1. generating the boundary value
  2. construct the body, using the boundary value from 1
  3. calculate the length of the body
  4. construct the headers, using the boundary value from 1 and the body length from 3
  5. submit the post on session

Hope that helps,

Dave.

2 Likes