views:

4798

answers:

3

This is an almost-duplicate of http://stackoverflow.com/questions/68477/send-file-using-post-from-a-python-script, but I'd like to add a caveat: I need something that properly handles the encoding of fields and attached files. The solutions I've been able to find blow up when you throw unicode strings containing non-ascii characters into the mix. Also, most of the solutions don't base64-encode data to keep things 7-bit clean.

A: 

Best thing I can think of is to encode it yourself. How about this subroutine?

from urllib2 import Request, urlopen
from binascii import b2a_base64

def b64open(url, postdata):
  req = Request(url, b2a_base64(postdata), headers={'Content-Transfer-Encoding': 'base64'})
  return urlopen(req)

conn = b64open("http://www.whatever.com/script.cgi", u"Liberté Égalité Fraternité")
# returns a file-like object

(Okay, so this code just sends POST-data. But you apparently want multipart-encoded data, as if you clicked an "Upload File" button, right? Well, it's a pretty straightforward combination of what I have here and the answers from the question you linked.)

Dan
+1  A: 

PyCURL provides an interface to CURL from Python.

http://curl.haxx.se/libcurl/python/

Curl will do all you need. It can transfer binary files properly, and supports many encodings. However, you have to make sure that the proper character encoding as a custom header when POSTing files.

Specifically, you may need to do a 'file upload' style POST:

http://curl.haxx.se/docs/httpscripting.html (Section 4.3)

With curl (or any other HTTP client) you may have to set the content encoding:

Content-Type: text/html; charset=UTF-8

Also, be aware that the request headers must be ascii, and this includes the url (so make sure you properly escape your possibly unicode URLs. There are unicode escapes for the HTTP headers) This was recently fixed in Python:

http://bugs.python.org/issue3300

I hope this helps, there is more info on the topic, including setting your default character set on your server, etc.

Chris
A: 

Just use this library and send in files.

http://github.com/seisen/urllib2_file/

Stattrav