Facing Issue with testing File Upload API using robot framework

I am very new to testing / developing. I am currently testing a REST API. In Postman I send a POST request by specifying parameters and uploading a file using form-data in the body. My request always succeeds in postman. However, when I try to translate this into Robot Framework (using the Requests Library) file is not getting selected in the request body(displaying content present in a file in the body).
I am posting my code below.
I have been trying to resolve this issue for a while now. Any help in the right direction would be much appreciated!

*** Test Cases ***
TC001

 create session  mysession     ${uri}
   
  ${file_name}=  Get Binary File  ${CURDIR}//test.txt
  
  ${asset}=  Create Dictionary   asset={file_name} 
     
  
 ${header}=  create dictionary   Accept=text/plain      Content-Type=multipart/form-data boundary    

${response}=    post request   mysession  /api/insertFile     data=${file_name}  headers=${header}
log to console      ${response.content}
  #to validate status code with the actual status code
 ${Status_code}=    convert to string   ${response.status_code}
 should be equal    ${Status_code}      200

 #to validate the content of the response body
 ${response_body}=  convert to string   ${response.content}
 should contain     ${response_body}    true

Response -
20200521 21:36:58.725 : INFO : Creating Session using : alias=mysession, url=https://someurl.com, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
20200521 21:36:58.727 : INFO : Getting file ‘C:\Users\fl792\eclipse-workspace\APITesting\API\test.txt’.
20200521 21:36:58.727 : INFO : {file_name} = lsjkgbsdkjb 20200521 21:36:58.729 : INFO : {asset} = {‘asset’: ‘{file_name}’}
20200521 21:36:58.730 : INFO : ${header} = {‘Accept’: ‘text/plain’, ‘Content-Type’: ‘multipart/form-data boundary’}
20200521 21:37:00.863 : INFO : POST Request : url=https://someurl/api/insertFile
path_url=/api/insertFile
headers={‘User-Agent’: ‘python-requests/2.23.0’, ‘Accept-Encoding’: ‘gzip, deflate’, ‘Accept’: ‘text/plain’, ‘Connection’: ‘keep-alive’, ‘Content-Type’: ‘multipart/form-data boundary’, ‘Content-Length’: ‘12’}
body=b’lsjkgbsdkjb ’

20200521 21:37:00.865 : INFO : POST Response : url=https://someurl/api/insertFile
status=200, reason=OK
body=false

Multipart should not be needed if you want to upload one single file.
Could you try with this new keywords instead of Get Binary File?
https://marketsquare.github.io/robotframework-requests/doc/RequestsLibrary.html#Get%20File%20For%20Streaming%20Upload

Let me know.

2 Likes

Thanks for the help. I tried this solution but still that file not getting uploaded

This API is working fine in swagger and postman

curl -X POST “https://some.com/api/insertFile” -H “accept: text/plain” -H “Content-Type: multipart/form-data” -F “asset=@Albany_Accomodations.pdf;type=application/pdf”
Curl URL

below is my code with new keyword

create session mysession ${uri}

${filepath}   Get File For Streaming Upload     ${CURDIR}${/}test.txt
${header}=  create dictionary     Accept=text/plain   Content-Type=multipart/form-data boundary   
${response}=    post request   mysession   /api/insertFile    asset=${filepath}   headers=${header}  
log to console      ${response.content}
  #to validate status code with the actual status code
 ${Status_code}=    convert to string   ${response.status_code}
 should be equal    ${Status_code}      200
 #to validate the content of the response body
 ${response_body}=  convert to string   ${response.content}
 should contain     ${response_body}    true

Server Log
20200522 02:39:57.418 : INFO : Creating Session using : alias=mysession, url=https://somurl.com, headers={}, cookies={}, auth=None, timeout=None, proxies=None, verify=False, debug=0
20200522 02:39:57.420 : INFO : {filepath} = <_io.BufferedReader name='C:\\Users\\fl792\\eclipse-workspace\\APITesting\\API\\test.txt'> 20200522 02:39:57.424 : INFO : {header} = {‘Accept’: ‘text/plain’, ‘Content-Type’: ‘multipart/form-data boundary’}
20200522 02:39:58.791 : INFO : POST Request : url=https://somurl.com/api/insertFile
path_url=/api/insertFile
headers={‘User-Agent’: ‘python-requests/2.23.0’, ‘Accept-Encoding’: ‘gzip, deflate’, ‘Accept’: ‘text/plain’, ‘Connection’: ‘keep-alive’, ‘Content-Type’: ‘multipart/form-data boundary’, ‘Content-Length’: ‘96’}
body=asset=<_io.BufferedReader name=‘C:\Users\fl792\eclipse-workspace\APITesting\API\test.txt’>
20200522 02:39:58.793 : INFO : POST Response : url=https://somurl.com/api/insertFile
status=200, reason=OK
body=false
20200522 02:39:58.796 : INFO : {response} = <Response [200]> 20200522 02:39:58.809 : INFO : {Status_code} = 200
20200522 02:39:58.820 : INFO : ${response_body} = false
20200522 02:39:58.826 : FAIL : ‘false’ does not contain ‘true’

You should change asset= with data=

{response}= post request mysession /api/insertFile data={filepath} headers=${header}

Changed and verified still getting false response

Server response
POST Request : url=https://someurl.com/api/insertFile
path_url=/api/insertFile
headers={‘User-Agent’: ‘python-requests/2.23.0’, ‘Accept-Encoding’: ‘gzip, deflate’, ‘Accept’: ‘text/plain’, ‘Connection’: ‘keep-alive’, ‘Content-Type’: ‘multipart/form-data boundary’, ‘Content-Length’: ‘12’}
body=<_io.BufferedReader name=‘C:\Users\fl792\eclipse-workspace\APITesting\API\test.txt’>

12:38:02.520 INFO POST Response : url=https://someurl.com/api/insertFile
status=200, reason=OK
body=false

@SuperSonic so status=200 and reason=OK does not indicate successful upload ? are you sure that there should be something in the body ? and you have checked that file was not actually uploaded ? :wink: … just confirming some things

Yes there is something in the body not sure what is, I should get a response as true but getting false. Checked with Get requests but not seeing the latest file uploaded.
let me know if any more information required.

Have you tried with files parameter ? @SuperSonic

${file_data}=  Get Binary File  ${CURDIR}${/}data.json
&{files}=  Create Dictionary  file=${file_data}
${resp}=  Post Request  mysession  /api/insertFile  files=${files}

Yes, I have tried this before, Get Binary File keyword copies data from the file. I want to upload any specific file it could be .txt file, .docx file, .xls file, .pdf file on the server by using file upload API. Posting details of API from swagger this time hope it will help us to find the issue.!!

Here is the successful one

I tried every possible way to fix this issue but no luck. :slightly_frowning_face:

Any solution?

Any lead on this issue will be appreciated.
Thanks

i am very sorry that i can not help you with this answer.
You can also try to ask in Slack…

https://robotframework.org/#community

For tmp workaround try using KW Run from Operating System library. And use curl command copied from swagger / exported from Postman.

I think I found the issue, you were passing the content-type header while requests will handle it automatically adding the boundary.

Here an example: robotframework-requests/test_post_multipart.robot at master · MarketSquare/robotframework-requests · GitHub

And more info here: Multiple fields in one multipart/form-data request part · Issue #218 · MarketSquare/robotframework-requests · GitHub