John J. Lee wrote:
Jeff Shannon <je**@ccvcorp.c om> writes:
[...]
I've been using something closely modelled on that Cookbook recipe,
without any real problems. (I've updated it to use
HTTP[S]Connection() and return the response object, and in my case I'm
connecting to an HTTPS server, but these are trivial modifications.)
[...]
Have you published your function? If not, please do.
Here it is, for what it's worth. (Hopefully my mailer won't mangle the
indentation...) As I noted, the differences between this and the
Cookbook recipe are minimal -- I literally copied the recipe into my
editor and made a few changes.
If I were going to put further effort into polishing it for library use
(which I probably won't have much opportunity to do), I'd make at least
two changes. One would be to set it up to select between HTTP and
HTTPS. (It currently tries to determine the protocol from the hostname
string, but does nothing with that information.) The other would be to
enable the file-subpart to add a Content-type header. (This is
irrelevant for my particular application, as the form(s) I'm uploading
to don't care.)
In case it matters to anyone, inasmuch as this code is nearly identical
to the published recipe, my changes can be considered to be under the
same license as the original recipe. If someone feels like using this
in any way, feel free.
Jeff Shannon
Technician/Programmer
Credit International
#! /usr/bin/python
import httplib
def post_multipart( host, selector, fields, files):
"""
Post fields and files to an http host as multipart/form-data.
fields is a sequence of (name, value) elements for regular form fields.
files is a sequence of (name, filename, value) elements for data to be uploaded as files.
Return an appropriate httplib.HTTPRes ponse object.
"""
content_type, body = encode_multipar t_formdata(fiel ds, files)
protocol = host.split(':')[0]
h = httplib.HTTPSCo nnection(host)
h.putrequest('P OST', selector)
h.putheader('co ntent-type', content_type)
h.putheader('co ntent-length', str(len(body)))
h.endheaders()
h.send(body)
response = h.getresponse()
return response
def encode_multipar t_formdata(fiel ds, files):
"""
fields is a sequence of (name, value) elements for regular form fields.
files is a sequence of (name, filename, value) elements for data to be uploaded as files.
Return (content_type, body) ready for httplib.HTTPCon nection instance
"""
BOUNDARY = '----------ThIs_Is_tHe_bou NdaRY_---$---'
CRLF = '\r\n'
L = []
for (key, value) in fields:
L.append('--' + BOUNDARY)
L.append('Conte nt-Disposition: form-data; name="%s"' % key)
L.append('')
L.append(value)
for (key, filename, value) in files:
L.append('--' + BOUNDARY)
L.append('Conte nt-Disposition: form-data; name="%s"; filename="%s"' % (key, filename))
L.append('')
L.append(value)
L.append('--' + BOUNDARY + '--')
L.append('')
body = CRLF.join(L)
content_type = 'multipart/form-data; boundary=%s' % BOUNDARY
return content_type, body