0

I am trying to upload a file using Python but I am not able to represent the same code as in CURL. I have a CURL command that it's working fine with the following call:

curl -X POST 
https://my_domain/workers 

-H 'Cache-Control: no-cache' 
-H 'Content-Type: multipart/form-data' 
-H 'content-type: multipart/form-data; boundary=----0987' 

-F myId=1234 
-F file=@<FILE_PATH>

My Python code is like this:

headers = {
    'Cache-Control': 'no-cache',
    'Content-Type': 'multipart/form-data',
    'content-type': 'multipart/form-data; boundary=----0987'
}
files = {
    'myId': workspace_id,
    'file': open(<FILE_PATH>, 'rb')
}

res = requests.post('https://my_domain/workers', headers=headers, files=files)

But when I call with Python I receive a result from the API telling that myId parameter is missing, but the same call is working in CURL. Does anyone have any idea?

Testing with https://httpbin.org/post I have the following results:

{
  "args": {}, 
  "data": "", 
  "files": {
    "myId": "1234", 
    "file": "<file content>"
  }, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Content-Length": "23430", 
    "Content-Type": "multipart/form-data; boundary=<random number>", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.19.1"
  }, 
  "json": null, 
  "origin": "<IP>", 
  "url": "https://httpbin.org/post"
}

But this way I receive error 500 from the response. Weird because CURL command is really working as expected. I also tried removing headers dic from the call and the same problem occurred.

Thank you very much!

briba
  • 2,857
  • 2
  • 31
  • 59
  • You have **two** content-type headers. You should not set *either*, because `requests` needs to generate this for you. I'd remove the `headers` altogether; an API with a caching layer that caches POST responses would be unexpected and broken. – Martijn Pieters Apr 16 '19 at 16:12
  • Setting the `content-type` header prevents `requests` from communicating the generated boundary that is used between the different parts of the POST body. – Martijn Pieters Apr 16 '19 at 16:14
  • @MartijnPieters thanks for your help! But actually even removing headers dic I still receive the error of missing myId parameter. – briba Apr 16 '19 at 16:45
  • Then something else is wrong; the `requests.post(url, files={'myId': value, 'file': openfileobject})` is the correct translation of the `curl` command-line given. Without details on the specific API being called (preferably a local MCVE or otherwise the documentation of the API) this isn't something we can help with here. – Martijn Pieters Apr 16 '19 at 17:18
  • (I did make an incorrect call regarding the `Cache-Control` header, but caching a POST response would mean there is a a bad cache config somewhere. By all means, use it on this request but I'd be surprised it makes a difference). – Martijn Pieters Apr 16 '19 at 17:19
  • 1
    For troubleshooting, I'd replace `https://mydomain/workers` with `https://httpbin.org/post` and inspect what's different between the responses to the `curl` command and the Python `requests.post()` call. – Martijn Pieters Apr 16 '19 at 17:21
  • @MartijnPieters thanks for your link, it's helping me a lot! I think the problem is because the custom boundary but I still don't know how to make it work with files. files={} is never being filled when I use header dic. Any ideas? – briba Apr 17 '19 at 09:04
  • Don’t set a custom boundary! There should never be a need to set a boundary, and the encoder will not use the boundary you set in the header. – Martijn Pieters Apr 17 '19 at 09:06
  • @MartijnPieters thanks man! I also posted result from httpbin. It looks like everything is there but I am receiving error 500 with my code (CURL command is working fine). Oo – briba Apr 17 '19 at 09:17
  • Without server details and concrete code to reproduce the httpbin results from both Python and curl (so we can analyse what differs) we really can’t help. – Martijn Pieters Apr 17 '19 at 10:43
  • @MartijnPieters actually I was able to solve it! I used only CacheControl and I created files parameter like a tuple: 'file': ('./csv_file', open(filepath, 'rb')) thank you very much for all your help! – briba Apr 17 '19 at 12:01

0 Answers0