aiohttp 异步http请求-4.文件上传multipart/form-data
Posted 上海-悠悠
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了aiohttp 异步http请求-4.文件上传multipart/form-data相关的知识,希望对你有一定的参考价值。
前言
文件上传接口,post 请求参数类型content-type:multipart/form-data,上传文件分2种情况
- 小文件上传,可以直接用open函数读取
- 大文件上传,aiohttp支持多种类型的文件以流媒体的形式上传
官方文档示例
上传 multipart 类型
url = 'http://httpbin.org/post'
files = 'file': open('report.xls', 'rb')
await session.post(url, data=files)
也可以明确设置filename
和 content_type
url = 'http://httpbin.org/post'
data = FormData()
data.add_field('file',
open('report.xls', 'rb'),
filename='report.xls',
content_type='application/vnd.ms-excel')
await session.post(url, data=data)
参考案例
用fiddler抓包,查看抓到的接口,以下这种接口就是multipart/form-data
Content-Type: multipart/form-data
body参数是这种格式:
-----------------------------22165374713946
Content-Disposition: form-data; name=“localUrl”
yoyoketang.png
-----------------------------22165374713946
Content-Disposition: form-data; name=“imgFile”; filename=“yoyoketang.png”
Content-Type: image/png
上面的接口需要传2个参数
- title 传字符串
- file 传一个文件
官网文档写的是只传一个file参数,实际验证也可以传其它字符串参数,如下示例:
import aiohttp
import asyncio
async def main():
async with aiohttp.ClientSession('http://127.0.0.1:8000') as session:
files =
'file': open('a.jpg', 'rb'),
'title': '文件上传'
async with session.post('/api/v1/upfile/', data=files) as resp:
print(resp.url)
print(await resp.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
运行结果
http://http://127.0.0.1:8000/api/v1/upfile/
"code":0,"msg":"success!","data":"file":"/media/up_image/a_TEn5GLR.jpg","title":"文件上传","timestamp":"2022-04-21 11:15:28"
使用 FormData 类
FormData 类自定义文件类型和名称
import aiohttp
import asyncio
from aiohttp import FormData
async def main():
async with aiohttp.ClientSession('http://49.235.92.12:7005') as session:
data = FormData()
data.add_field('file',
open('a.jpg', 'rb'),
filename='a.jpg',
content_type='image/png')
data.add_field('title', '文件上传1')
async with session.post('/api/v1/upfile/', data=data) as resp:
print(resp.url)
print(await resp.text())
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
大文件上传
小文件上传可以直接open函数读取,大文件直接读取会非常消耗内容。aiohttp支持多种类型的流式上传,这使您可以发送大文件而无需将它们读入内存。
作为一个简单的案例,只需为您的 body 提供一个类似文件的对象:
with open('massive-body', 'rb') as f:
await session.post('http://httpbin.org/post', data=f)
或者您可以使用异步生成器:
async def file_sender(file_name=None):
async with aiofiles.open(file_name, 'rb') as f:
chunk = await f.read(64*1024)
while chunk:
yield chunk
chunk = await f.read(64*1024)
# Then you can use file_sender as a data provider:
async with session.post('http://httpbin.org/post',
data=file_sender(file_name='huge_file')) as resp:
print(await resp.text())
因为该 content 属性是一个 StreamReader(提供异步迭代器协议),所以您可以将 get 和 post 请求链接在一起:
resp = await session.get('http://python.org')
await session.post('http://httpbin.org/post',
data=resp.content)
笔记 Python 3.5 没有对异步生成器的原生支持,使用 async_generator库作为解决方法。
3.1 版后已弃用:aiohttp仍支持aiohttp.streamer装饰器,但不推荐使用此方法,而支持异步生成器,如上所示。
以上是关于aiohttp 异步http请求-4.文件上传multipart/form-data的主要内容,如果未能解决你的问题,请参考以下文章
aiohttp 异步http请求-5.下载大文件边下载边保存(节省内存)
Python学习---IO的异步[asyncio +aiohttp模块]
python asyncio 异步 I/O - 实现并发http请求(asyncio + aiohttp)