1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
|
# -*- coding: utf-8 -*-
# http://code.activestate.com/recipes/146306-http-client-to-post-using-multipartform-data/
import http.client
import mimetypes
import uuid
def post_multipart(host, selector, fields, files, charset="UTF-8"):
"""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 the server's response page.
"""
content_type, body = encode_multipart_formdata(fields, files, charset)
h = http.client.HTTPConnection(host)
h.putrequest("POST", selector)
h.putheader("Content-Type", content_type)
h.putheader("Content-Length", str(len(body)))
h.endheaders()
h.send(body)
resp = h.getresponse()
return resp.read()
def encode_multipart_formdata(fields, files, charset="UTF-8"):
"""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.HTTP instance
"""
BOUNDARY = b"----=_NextPart_" + uuid.uuid1().bytes
CRLF = b"\r\n"
L = []
for key, value in fields:
if isinstance(key, str):
key = key.encode(charset)
if isinstance(value, str):
value = value.encode(charset)
L.append(b"--" + BOUNDARY)
L.append(b'Content-Disposition: form-data; name="' + key + b'"')
L.append(b"Content-Type: text/plain; charset=" + charset.encode(charset))
L.append(b"")
L.append(value)
for key, filename, value in files:
if isinstance(key, str):
key = key.encode(charset)
if isinstance(filename, str):
filename = filename.encode(charset)
if isinstance(value, str):
value = value.encode(charset)
L.append(b"--" + BOUNDARY)
L.append(
b'Content-Disposition: form-data; name="'
+ key
+ b'"; filename="'
+ filename
+ b'"'
)
L.append(b"Content-Type: " + get_content_type(filename).encode(charset))
L.append(b"")
L.append(value)
L.append(b"--" + BOUNDARY + b"--")
L.append(b"")
body = CRLF.join(L)
content_type = b"multipart/form-data; boundary=" + BOUNDARY
return content_type, body
def get_content_type(filename):
if isinstance(filename, bytes):
filename = filename.decode("utf-8")
return mimetypes.guess_type(filename)[0] or "application/octet-stream"
|