Multipart Parser
The `multipart` library (v1.3.1) provides a robust parser for `multipart/form-data` requests, commonly used in web applications for handling file uploads and complex form submissions. It supports both synchronous and asynchronous parsing, making it suitable for various web frameworks. The project is actively maintained with periodic security updates.
Warnings
- breaking The `parse_form` function signature changed significantly in versions 1.x compared to older 0.x releases. Previously, it might have directly accepted a WSGI `environ` dictionary. Current versions (1.0.0+) expect a file-like object (e.g., `environ['wsgi.input']`), the `Content-Type` header string, and the `Content-Length` integer.
- breaking Versions prior to 1.2.2 and 1.3.1 are vulnerable to a Denial of Service (DoS) attack via CPU exhaustion and excessive memory consumption when processing specially crafted multipart requests. This is tracked as `GHSA-p2m9-wcp5-6qw3`.
- gotcha File-like objects returned for file fields in the `files` dictionary (e.g., `file_item.file`) are open streams. It is crucial to explicitly close these streams after processing their content to release system resources and avoid potential resource leaks, especially in high-traffic applications.
Install
-
pip install multipart
Imports
- parse_form
from multipart import parse_form
- parse_form_async
from multipart import parse_form_async
- create_form
from multipart import create_form
Quickstart
import io
from multipart import parse_form
# Simulate a multipart/form-data request body
boundary = "----WebKitFormBoundaryXYZ"
body_data = f"""--{boundary}
Content-Disposition: form-data; name="username"
testuser
--{boundary}
Content-Disposition: form-data; name="filefield"; filename="example.txt"
Content-Type: text/plain
This is a test file content.
--{boundary}--
"""
# Prepare the input for parse_form
body_bytes = body_data.encode('utf-8')
content_type = f"multipart/form-data; boundary={boundary}"
content_length = len(body_bytes)
# Create a file-like object (BytesIO for in-memory bytes)
body_stream = io.BytesIO(body_bytes)
# Parse the form
form, files = parse_form(body_stream, content_type, content_length)
# Access parsed data
print("Form fields:")
for name, value_list in form.items():
# Form fields can have multiple values, parse_form returns a list for each.
print(f" {name}: {', '.join(value.decode('utf-8') for value in value_list)}")
print("\nFiles:")
for name, file_list in files.items():
for file_item in file_list:
print(f" Field Name: {file_item.field_name}")
print(f" Filename: {file_item.filename}")
print(f" Content Type: {file_item.content_type}")
print(f" Content (first 50 chars): {file_item.file.read()[:50].decode('utf-8')}")
file_item.file.close() # Crucial to close the file-like object