dud*_*998 5 python multipartform-data python-requests python-asyncio aiohttp
我试图异步发送一些多部分编码的表单数据作为发布请求,主要是一个文件和其他两个字段。
在尝试使用 asyncio 之前,我正在使用 requests-toolbelt MultipartEncoder( https://github.com/requests/toolbelt )同步执行该过程,这对于普通请求非常有效,但在使用 aiohttp 进行异步时不起作用。aiohttp 提供了 2 个多部分类,一个FormData()类和一个MultipartWriter()类,这两个类都没有给我带来很大的成功。
经过一些测试,似乎不同之处在于,当我使用工具带时MultipartEncoder(),请求会form在发布请求的部分按原样发送数据。但是,当使用 aiohttp 时,请求被放入请求的body部分。不知道为什么他们的行为不同
def multipartencode() -> ClientResponse():
# Using MultipartEncoder
m = MultipartEncoder(
fields={'type': type_str,
'metadata': json.dumps(metadata),
'file': (filename, file, 'application/json')}
)
# Using FormData
data = FormData()
data.add_field('file', file, filename=filename,
content_type='multipart/form-data')
data.add_field('type', type_str, content_type='multipart/form-data')
data.add_field('metadata', json.dumps(metadata),
content_type='multipart/form-data')
# Using MultipartWriter
with MultipartWriter('multipart/form-data') as mpwriter:
part = mpwriter.append(
file, {'CONTENT-TYPE': 'multipart/form-data'})
part.set_content_disposition('form-data')
part = mpwriter.append_form([('type', type_str)])
part.set_content_disposition('form-data')
part = mpwriter.append_form([('metadata', json.dumps(metadata))])
part.set_content_disposition('form-data')
# send request with ClientSession()
resp = await session.post(url=url, data=data, headers=headers)
return resp
Run Code Online (Sandbox Code Playgroud)
如何正确格式化/构建多部分编码请求以使其使用 aiohttp 发送?
小智 3
我为此苦苦挣扎了几个小时。我的具体情况是将带有文件附件的电子邮件发送到 mailgun。上面的评论也解决了同样的问题。请在下面找到工作代码:
import asyncio
import aiohttp
async def send():
url = "<<mailgun_url>>"
api_key = "<<mailgun_api_key>>"
mail_gun_data = {
"from": "<<from>>",
"to": "<<to>>",
"subject": "Subject",
"text": "Testing Mailgun",
"attachment": open("<<file_path>>", "rb")
}
async with aiohttp.ClientSession() as session:
with aiohttp.MultipartWriter("form-data") as mp:
for key, value in mail_gun_data.items():
part = mp.append(value)
part.set_content_disposition('form-data', name=key)
resp = await session.post(
url,
auth=aiohttp.BasicAuth("api", api_key),
data=mp,
)
if __name__ == '__main__':
asyncio.run(
send()
)
Run Code Online (Sandbox Code Playgroud)
我希望这会有所帮助并节省某人的时间。