Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

parse-multipart-form-data

A small, streaming parser for HTTP multipart/form-data request bodies.

The parser consumes an iterable of byte chunks and yields a streaming event sequence for each uploaded file. It does not depend on a web framework or read from sockets itself, so callers control request-body I/O and where uploaded content is stored.

Installation

pip install parse-multipart-form-data

For local development from this checkout:

pip install -e .

Usage

from parse_multipart_form_data import (
    PartBegin,
    PartData,
    PartEnd,
    parse_multipart_form_data,
)

body_chunks = [
    b"--BOUNDARY\r\n",
    b'Content-Disposition: form-data; name="file"; filename="hello.txt"\r\n',
    b"\r\n",
    b"hello world\r\n",
    b"--BOUNDARY--\r\n",
]

output = None
for event in parse_multipart_form_data(
        "multipart/form-data; boundary=BOUNDARY", body_chunks):
    if isinstance(event, PartBegin):
        output = open(event.filename, "wb")
    elif isinstance(event, PartData):
        output.write(event.data)
    else:  # PartEnd
        output.close()

The event stream is:

  • PartBegin(filename) at the beginning of a file part;
  • PartData(bytes_chunk) for each file-content chunk; and
  • PartEnd(is_final) after its delimiter has been consumed.

Only parts with a filename or filename* parameter produce events; ordinary form fields are consumed and skipped. A valid RFC 6266 filename* (UTF-8 or ISO-8859-1) takes precedence over filename.

Delimiter compatibility

Only exact delimiter lines are supported:

--BOUNDARY\r\n
--BOUNDARY--\r\n

MIME transport padding (spaces or tabs after a delimiter) is not supported. Supporting arbitrary transport padding requires byte-by-byte input reading, which is inefficient in Python and rare in real-world multipart form uploads.

Boundary values may be quoted or unquoted, including RFC 2046 boundary characters such as =, :, /, ?, (, ), and ,. Preamble and part-header lines are limited to 8192 bytes of content.

Parser states

The parser has one MultipartState vocabulary. Its transitions are:

SEEK_OPENING_BOUNDARY -> READ_HEADERS | DONE
READ_HEADERS          -> MAYBE_BOUNDARY
READ_PART_BODY        -> READ_PART_BODY | MAYBE_BOUNDARY
MAYBE_BOUNDARY        -> MAYBE_BOUNDARY | READ_PART_BODY | READ_HEADERS | DONE

Minimal wire-format machine

For the multipart example in the module documentation, the parser's essential wire-level transitions are (CRLF denotes the literal \r\n byte pair):

stateDiagram-v2
    [*] --> SEEK_OPENING_BOUNDARY
    SEEK_OPENING_BOUNDARY --> READ_HEADERS: --BOUNDARY CRLF
    SEEK_OPENING_BOUNDARY --> DONE: --BOUNDARY-- CRLF
    READ_HEADERS --> READ_HEADERS: header CRLF
    READ_HEADERS --> MAYBE_BOUNDARY: blank CRLF / empty part check
    READ_PART_BODY --> READ_PART_BODY: not *.CRLF
    READ_PART_BODY --> MAYBE_BOUNDARY: *.CRLF
    MAYBE_BOUNDARY --> MAYBE_BOUNDARY: non-boundary line ending CRLF
    MAYBE_BOUNDARY --> READ_PART_BODY: non-boundary prefix
    MAYBE_BOUNDARY --> READ_HEADERS: --BOUNDARY CRLF
    MAYBE_BOUNDARY --> DONE: --BOUNDARY-- CRLF
    DONE --> [*]

The single parser generator holds its state across every event. A boundary suffix is consumed before it emits PartEnd, so the next event always starts a well-defined next transition.

Testing

python -m unittest discover -s tests

License

MIT. See LICENSE.

Release files for parse-multipart-form-data 0.1.0a0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for parse-multipart-form-data 0.1.0a0
File Size Uploaded
parse_multipart_form_data-0.1.0a0.tar.gz 9.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for parse-multipart-form-data 0.1.0a0
File Interpreter ABI Platform
parse_multipart_form_data-0.1.0a0-py2.py3-none-any.whl Python 2, Python 3 none any Details

Total release size: 17.4 kB

Release files / parse_multipart_form_data-0.1.0a0.tar.gz

Download URL parse_multipart_form_data-0.1.0a0.tar.gz
Size 9.6 kB
Tags Source
SHA-256 checksum
How to use checksums
70aca36ab031996683b6daa55bc24c707c9b8d60fb4e1373f107fb23d0bd3a83
BLAKE2b-256 checksum
How to use checksums
b0a0800cfeedf53d5f3b8a189b8ccd255aec9e423213a568f91eac5e7451637f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release files / parse_multipart_form_data-0.1.0a0-py2.py3-none-any.whl

Download URL parse_multipart_form_data-0.1.0a0-py2.py3-none-any.whl
Size 7.8 kB
Tags Python 2 Python 3
SHA-256 checksum
How to use checksums
ca63c9faae78939c65e02abe8f20500a745e60b29858ab5bc1773d49b8b1a861
BLAKE2b-256 checksum
How to use checksums
0fd909487b3cc513cbccccfd9a7c4fc635b3018d0fd7b1cc63deb3a21000b02b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.7

Release history Release notifications | RSS feed

This release

0.1.0a0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page