1

I am attempting to upload a CSV file to an API (which gives me very little error info) using python requests library.

(I'm running Python 3.5 and using requests version 2.18.4 on OS X 10.11.6)

This curl command in terminal works fine: curl -F 'file=@/path/to/file.csv' myurl.com/upload -H "Authorization: TOKEN sometoken"

A multipart/form-data POST request from Postman also works, but I can't seem to make it work with the python requests library.

I've tried many variations of this request:

import requests
headers = {'Authorization': 'TOKEN sometoken', 'Content-Type': 'multipart/form-data'}

with open(file_path, 'rb') as f:
    r = requests.post(myurl, headers=headers, data=f)

## I've also tried data={"file": f}

I get a status code of 200, but the response is {"success": "false"} (frustratingly unhelpful).

What am I missing in the python request compared to the curl request?

EDIT: it seems that the -F flag for the curl command emulates an HTML form that has been submitted...is there a way to do this with requests?

dukeluke
  • 646
  • 7
  • 22

2 Answers2

2

In your curl code you're using the -F parameter, which submits the data as a multipart message - in other words you're uploading a file.
With requests you can post files with the files parameter. An example:

import requests

headers = {'Authorization': 'TOKEN sometoken'}
data = {'file': open(file_path, 'rb')}
r = requests.post(myurl, headers=headers, files=data)

Note that requests creates the Content-Type header automatically, based on the submitted data.

t.m.adam
  • 15,106
  • 3
  • 32
  • 52
  • This worked, thanks! I noticed the `files` param in the docs, but they only mention it [specifically for multiple file uploads at the same time](http://docs.python-requests.org/en/master/user/advanced/#post-multiple-multipart-encoded-files), which threw me off. – dukeluke Apr 27 '18 at 23:25
  • 1
    That's the dvanced usage documentation (in case you want to upload multiple files with the same name), and it can be confusing. The example in [quickstart](http://docs.python-requests.org/en/master/user/quickstart/#post-a-multipart-encoded-file) in is much clearer. – t.m.adam Apr 27 '18 at 23:35
1

The python open() function returns a file object. This is not what you want to send to the API.
Instead, you can use:

with open(file_path, 'rb') as f:
    r = requests.post(myurl, headers=headers, data=f.read())

Syntax taken from here.

Fire
  • 393
  • 1
  • 7
  • Unfortunately, that didn't do the trick. I wish I could provide more info, but I have absolutely no error info to go on. – dukeluke Apr 27 '18 at 22:41