Ejemplo n.º 1
0
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
Ejemplo n.º 2
0
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
Ejemplo n.º 3
0
 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
Ejemplo n.º 4
0
    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'),
                                 ])
Ejemplo n.º 5
0
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