如何使用aiohttp POST提交octet-stream类型multipart formdata请求
aiohttp 发送 octet-stream 类型 multipart 请求实现方案
核心逻辑:aiohttp 原生的FormData类已经完整支持multipart格式编码,你只需要在添加文件字段时指定二进制流类型即可,不需要手动修改全局请求头,手动改头反而会导致boundary参数丢失,服务端解析失败。
实现步骤
- 导入aiohttp内置的
FormData类,不要用普通Python字典构造请求体 - 调用
add_field方法添加文件字段时,显式传入content_type='application/octet-stream',同时必须填写filename参数触发文件编码逻辑 - 发起请求时直接把FormData实例传给
data参数,不要手动设置Content-Type请求头,aiohttp会自动生成带正确boundary标识的multipart头 - 按接口要求添加鉴权等其他必要请求头即可
可直接运行的代码示例
import asyncio import aiohttp from pathlib import Path async def upload_avatar_check(avatar_path: str, auth_token: str): # 读取本地二进制文件 file_bytes = Path(avatar_path).read_bytes() # 初始化multipart表单 multipart_form = aiohttp.FormData() # 添加文件字段,按接口要求替换name参数为实际字段名 multipart_form.add_field( name="file", value=file_bytes, filename=Path(avatar_path).name, content_type="application/octet-stream" ) async with aiohttp.ClientSession() as session: async with session.post( url="替换为目标API的实际地址", data=multipart_form, headers={"Authorization": f"Bearer {auth_token}"} ) as response: # 按接口返回格式解析响应,这里以json为例 resp_data = await response.json() response.raise_for_status() return resp_data if __name__ == "__main__": result = asyncio.run(upload_avatar_check("test.png", "替换为你的实际鉴权token")) print(result)
常见踩坑说明
- 禁止用普通字典传文件参数:普通字典会被默认编码为
x-www-form-urlencoded格式,无法正确传输二进制流- 禁止手动设置Content-Type头:手动写死
multipart/form-data或application/octet-stream会覆盖aiohttp自动拼接的boundary参数,服务端无法拆分表单字段- 必须传filename参数:不传该参数时aiohttp会把二进制内容当成普通文本字段编码,不符合文件上传的格式要求
- 极端场景适配:如果目标接口强制校验顶层Content-Type为
application/octet-stream,可以在构造完form后手动拼接头,保留自动生成的boundary:headers["Content-Type"] = f"application/octet-stream; boundary={multipart_form.boundary}"
内容的提问来源于stack exchange,提问作者GoogolGenius
相关产品推荐
相关产品推荐

