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
|
import itertools
from mimetypes import guess_type
from email.generator import _make_boundary
class MultiPartForm(dict):
def __init__(self):
self.files = []
self.boundary = _make_boundary()
def get_content_type(self):
return "multipart/form-data; boundary=%s" % self.boundary
def add_file(self, fieldname, filename, fd, mimetype=None):
body = fd.read()
if mimetype is None:
mimetype = guess_type(filename)[0] or "application/octet-stream"
self.files.append((fieldname, filename, mimetype, body))
def bytes(self):
parts = []
part_boundary = bytearray("--%s" % self.boundary, "ascii")
# Add the form fields
parts.extend([
part_boundary,
bytearray(
"Content-Disposition: form-data; name=\"%s\"" % k,
"ascii"
),
bytes(),
v if isinstance(v, bytes) else bytearray(v, "ascii")
] for k, v in list(self.items()))
# Add the files to upload
parts.extend([
part_boundary,
bytearray(
"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"" % (
fieldname, filename),
"ascii"
),
bytearray("Content-Type: %s" % content_type, "ascii"),
bytearray(),
body if isinstance(body, bytes) else bytearray(body, "ascii"),
] for fieldname, filename, content_type, body in self.files)
# Flatten the list and add closing boundary marker,
# then return CR+LF separated data
flattened = list(itertools.chain(*parts))
flattened.append(bytearray("--%s--" % self.boundary, "ascii"))
res = bytearray()
for item in flattened:
res += item
res += bytearray("\r\n", "ascii")
return res
|