multipart/form-data 解析器
项目描述
此模块提供了RFC-7578 multipart/form-data的多个解析器,既有针对框架作者的底层解析器,也有针对WSGI应用开发者的高层解析器。
PushMultipartParser:一个适合asyncio和其他时间或内存受限环境的底层增量 SansIO(非阻塞)解析器。
MultipartParser:一个流式解析器,生成内存和磁盘缓冲的 MultipartPart 实例。
parse_form_data:一个辅助函数,用于从WSGI环境解析 multipart/form-data 和 application/x-www-form-urlencoded 表单提交。
安装
pip install multipart
特性
纯Python单文件模块,无依赖。
100%测试覆盖率。使用实际浏览器和HTTP客户端的输入进行测试。
在现代硬件上解析多个GB/s(快速测试,无正式基准测试)。
快速拒绝恶意或损坏的输入,并发出有用的错误信息。
强制执行可配置的内存和磁盘资源限制,以防止DoS攻击。
限制:该解析器实现了与实际现代浏览器和HTTP客户端相同的使用方式multipart/form-data,这意味着
仅支持multipart/form-data,不适用于电子邮件解析。
不支持multipart/mixed(在RFC 7578中被弃用)。
不支持base64或quoted-printable传输编码(在RFC 7578中被弃用)。
不支持encoded-word或name=_charset_编码标记(在RFC 7578中被不鼓励使用)。
不支持明显损坏的输入(例如无效的换行符或头名称)。
使用和示例
对于WSGI应用程序开发者,我们强烈建议使用parse_form_data辅助函数。它接受一个WSGI environ字典,并根据请求的实际内容类型解析两种类型的表单提交(multipart/form-data和application/x-www-form-urlencoded)。您将返回两个MultiDict实例,一个用于文本字段,另一个用于文件上传
from multipart import parse_form_data
def wsgi(environ, start_response):
if environ["REQUEST_METHOD"] == "POST":
forms, files = parse_form_data(environ)
title = forms["title"] # string
upload = files["upload"] # MultipartPart
upload.save_as(...)
parse_form_data辅助函数内部使用MultipartParser,这是一个流式解析器,它从multipart/form-data编码的二进制数据流中读取,并在完全解析一个部分后立即发出MultipartPart实例。如果您想尽快消费各个部分,而不是等待整个请求被解析,这将非常有用
from multipart import parse_options_header, MultipartParser
def wsgi(environ, start_response):
assert environ["REQUEST_METHOD"] == "POST"
ctype, copts = parse_options_header(environ.get("CONTENT_TYPE", ""))
boundary = copts.get("boundary")
charset = copts.get("charset", "utf8")
assert ctype == "multipart/form-data"
parser = MultipartParser(environ["wsgi.input"], boundary, charset)
for part in parser:
if part.filename:
print(f"{part.name}: File upload ({part.size} bytes)")
part.save_as(...)
elif part.size < 1024:
print(f"{part.name}: Text field ({part.value!r})")
else:
print(f"{part.name}: Test field, but too big to print :/")
MultipartParser为您处理IO和文件缓冲,但它使用阻塞API。如果您需要完全控制解析过程,并且不惜一切代价避免阻塞IO,那么请查看PushMultipartParser,这是一个低级非阻塞增量multipart/form-data解析器,为该库中的所有其他解析器提供动力
from multipart import PushMultipartParser, MultipartSegment
async def process_multipart(reader: asyncio.StreamReader, boundary: str):
with PushMultipartParser(boundary) as parser:
while not parser.closed:
chunk = await reader.read(1024*64)
for result in parser.parse(chunk):
if isinstance(result, MultipartSegment):
print(f"== Start of segment: {result.name}")
for header, value in result.headerlist:
print(f"{header}: {value}")
elif result: # Result is a non-empty bytearray
print(f"[received {len(result)} bytes of data]")
else: # Result is None
print(f"== End of segment")
变更日志
1.1
其中一些修复更改了行为以匹配文档或规范,其中没有一个应该令人惊讶。现有应用程序应该能够在不进行更改的情况下升级。
修复:在输入包含无效换行符时更快失败(#55)
修复:允许空段名称(#56)
修复:在使用parse_form_data时避免ResourceWarning(#57)
修复:MultipartPart现在始终具有合理的MIME类型。
修复:在上下文管理器退出时实际检查解析器状态。
修复:如果存在,则尊重Content-Length头。
性能:减少小段落的开销(-21%)
性能:减少大上传的写入开销(-2%)
1.0
一个全新的、快速的、非阻塞的PushMultipartParser解析器,现在作为所有其他解析器的基础。
新解析器更加严格,并且在非严格模式下更快地拒绝明显损坏的输入(例如无效的换行符或头名称)。这不应影响实际浏览器或HTTP客户端发送的数据。
MultipartParser头和文本字段的默认字符集更改为utf8,如W3C HTTP建议。
MultipartParser的默认磁盘和内存限制已提高,但添加了多个其他限制以实现更精细的控制。请检查新默认值是否满足您的需求。
未记录的API已弃用或删除,其中一些并非严格私有。这包括MultipartParser的参数和一些MultipartPart方法,但它们不应该被除解析器自身之外的人使用。
0.2.5
不要在urlencoded数据中测试分号分隔符(#33)
添加python-requires指令,指示需要Python 3.5或更高版本,并防止旧版本的Python尝试下载此版本(#32)
添加对Python 3.10-3.12的官方支持(#38,#48)
copy_file的默认值应为2 ** 16,而不是2 * 16(#41)
更新Bottle的URL(#42)
0.2.4
始终解码非UTF-8 URL编码的表单数据
0.2.3
从collections.abc导入MutableMapping(#23)
修复测试套件中的几个ResourceWarnings(#24)
允许流在第一个边界之前包含数据(#25)
0.2.2
修复Python 3上的#21 ResourceWarnings(#25)
0.2.1
修复#20空有效载荷(#20)
0.2
已取消对低于3.6版本的Python的支持。如果您需要Python 2.5+支持,请保持在0.1版本。
0.1
第一个版本
项目详情
下载文件
为您的平台下载文件。如果您不确定选择哪个,请了解更多关于安装包的信息。