| 105 | | def parse_file_upload(header_dict, post_data): |
|---|
| 106 | | """Returns a tuple of (POST QueryDict, FILES MultiValueDict).""" |
|---|
| 107 | | import email, email.Message |
|---|
| 108 | | from cgi import parse_header |
|---|
| 109 | | raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()]) |
|---|
| 110 | | raw_message += '\r\n\r\n' + post_data |
|---|
| 111 | | msg = email.message_from_string(raw_message) |
|---|
| 112 | | POST = QueryDict('', mutable=True) |
|---|
| 113 | | FILES = MultiValueDict() |
|---|
| 114 | | for submessage in msg.get_payload(): |
|---|
| 115 | | if submessage and isinstance(submessage, email.Message.Message): |
|---|
| 116 | | name_dict = parse_header(submessage['Content-Disposition'])[1] |
|---|
| 117 | | # name_dict is something like {'name': 'file', 'filename': 'test.txt'} for file uploads |
|---|
| 118 | | # or {'name': 'blah'} for POST fields |
|---|
| 119 | | # We assume all uploaded files have a 'filename' set. |
|---|
| 120 | | if 'filename' in name_dict: |
|---|
| 121 | | assert type([]) != type(submessage.get_payload()), "Nested MIME messages are not supported" |
|---|
| 122 | | if not name_dict['filename'].strip(): |
|---|
| 123 | | continue |
|---|
| 124 | | # IE submits the full path, so trim everything but the basename. |
|---|
| 125 | | # (We can't use os.path.basename because that uses the server's |
|---|
| 126 | | # directory separator, which may not be the same as the |
|---|
| 127 | | # client's one.) |
|---|
| 128 | | filename = name_dict['filename'][name_dict['filename'].rfind("\\")+1:] |
|---|
| 129 | | FILES.appendlist(name_dict['name'], FileDict({ |
|---|
| 130 | | 'filename': filename, |
|---|
| 131 | | 'content-type': 'Content-Type' in submessage and submessage['Content-Type'] or None, |
|---|
| 132 | | 'content': submessage.get_payload(), |
|---|
| 133 | | })) |
|---|
| 134 | | else: |
|---|
| 135 | | POST.appendlist(name_dict['name'], submessage.get_payload()) |
|---|
| 136 | | return POST, FILES |
|---|
| 137 | | |
|---|
| | 107 | def _initialize_handlers(self): |
|---|
| | 108 | self._upload_handlers = [uploadhandler.load_handler(handler, self) |
|---|
| | 109 | for handler in settings.FILE_UPLOAD_HANDLERS] |
|---|
| | 110 | |
|---|
| | 111 | def _set_upload_handlers(self, upload_handlers): |
|---|
| | 112 | if hasattr(self, '_files'): |
|---|
| | 113 | raise AttributeError("You cannot set the upload handlers after the upload has been processed.") |
|---|
| | 114 | self._upload_handlers = upload_handlers |
|---|
| | 115 | |
|---|
| | 116 | def _get_upload_handlers(self): |
|---|
| | 117 | if not self._upload_handlers: |
|---|
| | 118 | # If thre are no upload handlers defined, initialize them from settings. |
|---|
| | 119 | self._initialize_handlers() |
|---|
| | 120 | return self._upload_handlers |
|---|
| | 121 | |
|---|
| | 122 | upload_handlers = property(_get_upload_handlers, _set_upload_handlers) |
|---|
| | 123 | |
|---|
| | 124 | def parse_file_upload(self, META, post_data): |
|---|
| | 125 | """Returns a tuple of (POST QueryDict, FILES MultiValueDict).""" |
|---|
| | 126 | self.upload_handlers = ImmutableList( |
|---|
| | 127 | self.upload_handlers, |
|---|
| | 128 | warning = "You cannot alter upload handlers after the upload has been processed." |
|---|
| | 129 | ) |
|---|
| | 130 | parser = MultiPartParser(META, post_data, self.upload_handlers, self.encoding) |
|---|
| | 131 | return parser.parse() |
|---|