前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >aiohttp 异步http请求-4.文件上传multipart/form-data

aiohttp 异步http请求-4.文件上传multipart/form-data

作者头像
上海-悠悠
发布2022-04-22 19:13:26
2.8K0
发布2022-04-22 19:13:26
举报
文章被收录于专栏:从零开始学自动化测试

前言

文件上传接口,post 请求参数类型content-type:multipart/form-data,上传文件分2种情况

  • 小文件上传,可以直接用open函数读取
  • 大文件上传,aiohttp支持多种类型的文件以流媒体的形式上传

官方文档示例

上传 multipart 类型

代码语言:javascript
复制
url = 'http://httpbin.org/post'
files = {'file': open('report.xls', 'rb')}

await session.post(url, data=files)

也可以明确设置filenamecontent_type

代码语言:javascript
复制
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

代码语言:javascript
复制
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参数,实际验证也可以传其它字符串参数,如下示例:

代码语言:javascript
复制
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())

运行结果

代码语言:javascript
复制
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 类自定义文件类型和名称

代码语言:javascript
复制
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 提供一个类似文件的对象:

代码语言:javascript
复制
with open('massive-body', 'rb') as f:
   await session.post('http://httpbin.org/post', data=f)

或者您可以使用异步生成器:

代码语言:javascript
复制
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 请求链接在一起:

代码语言:javascript
复制
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装饰器,但不推荐使用此方法,而支持异步生成器,如上所示。

2022年第 1 期《Python 测试平台开发》课程

2022年第 10 期《python接口web自动化+测试开发》课程,2月13号开学

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-04-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 从零开始学自动化测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 官方文档示例
  • 参考案例
  • 使用 FormData 类
  • 大文件上传
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档