OLD | NEW |
(Empty) | |
| 1 # urllib3/filepost.py |
| 2 # Copyright 2008-2012 Andrey Petrov and contributors (see CONTRIBUTORS.txt) |
| 3 # |
| 4 # This module is part of urllib3 and is released under |
| 5 # the MIT License: http://www.opensource.org/licenses/mit-license.php |
| 6 |
| 7 import codecs |
| 8 import mimetypes |
| 9 |
| 10 from uuid import uuid4 |
| 11 from io import BytesIO |
| 12 |
| 13 from .packages import six |
| 14 from .packages.six import b |
| 15 |
| 16 writer = codecs.lookup('utf-8')[3] |
| 17 |
| 18 |
| 19 def choose_boundary(): |
| 20 """ |
| 21 Our embarassingly-simple replacement for mimetools.choose_boundary. |
| 22 """ |
| 23 return uuid4().hex |
| 24 |
| 25 |
| 26 def get_content_type(filename): |
| 27 return mimetypes.guess_type(filename)[0] or 'application/octet-stream' |
| 28 |
| 29 |
| 30 def iter_fields(fields): |
| 31 """ |
| 32 Iterate over fields. |
| 33 |
| 34 Supports list of (k, v) tuples and dicts. |
| 35 """ |
| 36 if isinstance(fields, dict): |
| 37 return ((k, v) for k, v in six.iteritems(fields)) |
| 38 |
| 39 return ((k, v) for k, v in fields) |
| 40 |
| 41 |
| 42 def encode_multipart_formdata(fields, boundary=None): |
| 43 """ |
| 44 Encode a dictionary of ``fields`` using the multipart/form-data MIME format. |
| 45 |
| 46 :param fields: |
| 47 Dictionary of fields or list of (key, value) or (key, value, MIME type) |
| 48 field tuples. The key is treated as the field name, and the value as |
| 49 the body of the form-data bytes. If the value is a tuple of two |
| 50 elements, then the first element is treated as the filename of the |
| 51 form-data section and a suitable MIME type is guessed based on the |
| 52 filename. If the value is a tuple of three elements, then the third |
| 53 element is treated as an explicit MIME type of the form-data section. |
| 54 |
| 55 Field names and filenames must be unicode. |
| 56 |
| 57 :param boundary: |
| 58 If not specified, then a random boundary will be generated using |
| 59 :func:`mimetools.choose_boundary`. |
| 60 """ |
| 61 body = BytesIO() |
| 62 if boundary is None: |
| 63 boundary = choose_boundary() |
| 64 |
| 65 for fieldname, value in iter_fields(fields): |
| 66 body.write(b('--%s\r\n' % (boundary))) |
| 67 |
| 68 if isinstance(value, tuple): |
| 69 if len(value) == 3: |
| 70 filename, data, content_type = value |
| 71 else: |
| 72 filename, data = value |
| 73 content_type = get_content_type(filename) |
| 74 writer(body).write('Content-Disposition: form-data; name="%s"; ' |
| 75 'filename="%s"\r\n' % (fieldname, filename)) |
| 76 body.write(b('Content-Type: %s\r\n\r\n' % |
| 77 (content_type,))) |
| 78 else: |
| 79 data = value |
| 80 writer(body).write('Content-Disposition: form-data; name="%s"\r\n' |
| 81 % (fieldname)) |
| 82 body.write(b'\r\n') |
| 83 |
| 84 if isinstance(data, int): |
| 85 data = str(data) # Backwards compatibility |
| 86 |
| 87 if isinstance(data, six.text_type): |
| 88 writer(body).write(data) |
| 89 else: |
| 90 body.write(data) |
| 91 |
| 92 body.write(b'\r\n') |
| 93 |
| 94 body.write(b('--%s--\r\n' % (boundary))) |
| 95 |
| 96 content_type = str('multipart/form-data; boundary=%s' % boundary) |
| 97 |
| 98 return body.getvalue(), content_type |
OLD | NEW |