class FormDataReceiver(object): """Handle incoming multipart/form-data, and route it to storage classes. This is the main data receiver, to be used from within a RequestHandler. Keep pushing incoming multipart data into its data_received method, and remember to call finish() when done. Args: listener (ProgressListener): the listener to be notified of upload progress boundary (str): multipart mimetype boundary """ def __init__(self, listener, boundary, **kwargs): self._listener = listener self.headers = HeadersGatherer() self.parser = MultipartParser(boundary, { 'on_part_begin': self.on_part_begin, 'on_part_data': self.on_part_data, 'on_part_end': self.on_part_end, 'on_header_field': self.headers.on_header_field, 'on_header_value': self.headers.on_header_value, 'on_header_end': self.headers.on_header_end, 'on_headers_finished': self.on_headers_finished }) self._parts_received = {} self._current = None self._current_name = None def data_received(self, data): self.parser.write(data) def finish(self): self._listener.finish() def on_part_begin(self): self.headers.clear() def on_part_data(self, data, start, end): if self._current is not None: self._current.data_received(data[start:end]) total = None if self._current_name == 'upload' and 'filesize' in self._parts_received: desc = self._parts_received['filesize'].get_data() filename = self._current._filename total = desc[filename] self._listener.file_part_received(filename, end-start, total) def on_part_end(self): if self._current is not None: self._current.finish() self._current = None def on_headers_finished(self): disposition_header = self.headers['content-disposition'] disposition, options = parse_header_options(disposition_header) if disposition == 'form-data': self._current_name, self._current = _choose_input(disposition, options) self._parts_received[self._current_name] = self._current
def multipart(body, **header_params): """Converts multipart form data into native Python objects""" if header_params and 'boundary' in header_params: if type(header_params['boundary']) is str: header_params['boundary'] = header_params['boundary'].encode() parser = MultipartParser(stream=body, boundary=header_params['boundary'], disk_limit=17179869184) form = dict(zip([p.name for p in parser.parts()],\ [(p.filename,p.file) if p.filename else p.file.read().decode() for p in parser.parts()])) return form
def __init__(self, listener, boundary, **kwargs): self._listener = listener self.headers = HeadersGatherer() self.parser = MultipartParser(boundary, { 'on_part_begin': self.on_part_begin, 'on_part_data': self.on_part_data, 'on_part_end': self.on_part_end, 'on_header_field': self.headers.on_header_field, 'on_header_value': self.headers.on_header_value, 'on_header_end': self.headers.on_header_end, 'on_headers_finished': self.on_headers_finished }) self._parts_received = {} self._current = None self._current_name = None
async def handle(self, body): ctype = dict(self.scope['headers'])[b'content-type'] _, options = parse_options_header(ctype.decode()) mp = MultipartParser(BytesIO(body), options['boundary']) content = '' for part in mp.parts(): if part.filename: content = part.value await self.send_response(200, b'%d' % len(content), headers=[ ('Content-Type', 'text/plain; charset=utf-8'), ])
def form_multipart_decoder(request, response): ''' Exactly like :func:`form_url_decoder` except that file uploads are handled via the 'multipart' module. ''' if 'content_type' in request.headers: multipart_pattern = re.compile('^multipart/form-data; boundary=(.*)', re.I) match = multipart_pattern.match(request.headers.content_type) if match: mp = MultipartParser(request.wsgi.input, boundary=match.group(1)) for i in mp: if i.filename: response.additional_params[i.name] = i else: response.additional_params[i.name] = i.value
def _parse_multipart(self, header: str, body: str): boundary = None parts = header.split(';') for part in parts: if 'boundary=' in part: boundary = part.split('=')[-1] self.info('Boundary: %s', boundary) ret = {} body = base64.b64decode(body) parser = MultipartParser(io.BytesIO(body), boundary) for part in parser: if part.file and part.filename is not None: ret[part.name] = ff.File(name=part.filename, content=part.raw, content_type=part.content_type) else: ret[part.name] = part.value return ret