如何将带文件上传的requests POST请求转换为aiohttp ClientSession请求?
解决aiohttp中异步上传文件的问题
嗨,这个问题我之前也踩过坑!aiohttp和requests的文件上传逻辑确实不一样——它没有直接对应files的参数,得靠FormData类来手动构建multipart请求体。下面是具体的解决方法:
核心思路
Requests的files参数其实是帮你自动封装了multipart/form-data格式的请求,而aiohttp需要你手动用FormData来实现这个封装过程,把payload字段和文件一起添加到表单里。
完整代码示例
from aiohttp import ClientSession, FormData import json async def upload_file(url, headers, itemID, filename, file_src): # 先用字典构建variables,再转成JSON字符串(比手动拼接更安全) variables = {"item_id": itemID} payload = { 'query': 'mutation add_file($file: File!, $item_id: Int!) {add_file_to_column(item_id: $item_id, file: $file, column_id: fichier3) {id}}', 'variables': json.dumps(variables), 'map': json.dumps({"file": "variables.file"}) } # 构建FormData对象 form = FormData() # 添加payload中的所有字段 for key, value in payload.items(): form.add_field(key, value) # 异步打开文件(避免阻塞事件循环,异步编程最佳实践) async with open(file_src, 'rb') as file_stream: # 添加文件到表单 form.add_field( name='file', value=file_stream, filename=filename, content_type='file/csv' ) # 发送异步请求 async with ClientSession(trust_env=True) as session: # 用post方法更直观,request方法也可以 async with session.post(url, headers=headers, data=form) as response: return await response.json()
关键注意点
- 不要手动设置
Content-Type头:FormData会自动生成正确的multipart/form-data请求头(包含boundary),如果你的headers里原来有这个字段,建议删掉,否则可能导致请求格式错误。 - 用
json.dumps生成JSON字符串:代替你原来手动拼接带"的字符串,避免转义错误,代码也更易维护。 - 异步打开文件:使用
async with open(...)而不是同步的open(),防止阻塞异步事件循环,保证程序的并发性能。
内容的提问来源于stack exchange,提问作者JasonBeni
相关产品推荐
相关产品推荐

