複数のデータを送るときに使う multipart/form-data
を aiohttp で送る方法です。
公式ドキュメントは以下です。
基本サンプル
import asyncio
import aiohttp
async def main():
with aiohttp.MultipartWriter("form-data") as mpwriter:
mpwriter.append('hello1')
mpwriter.append('hello2')
async with aiohttp.ClientSession() as session:
res = await session.post(f'url', data=mpwriter)
print(res)
if __name__ == '__main__':
asyncio.run(main())
以下のような内容で送信されました。
Content-Type: multipart/form-data; boundary=69ae25abec5c4a038dc2deb4a0952eb3
--69ae25abec5c4a038dc2deb4a0952eb3
Content-Type: text/plain; charset=utf-8
Content-Length: 6
hello1
--69ae25abec5c4a038dc2deb4a0952eb3
Content-Type: text/plain; charset=utf-8
Content-Length: 6
hello2
--69ae25abec5c4a038dc2deb4a0952eb3--
テキストデータ
mpwriter.append
にテキストを渡した場合、デフォルトでは Content-Type
は text/plain
になるそうです。
バイナリデータ
mpwriter.append
にバイナリデータを渡した場合、デフォルトでは Content-Type
は application/octet-stream
になるそうです。
変更したい場合は以下のように第2引数で指定します。
mpwriter.append(image, {'Content-Type': 'image/jpeg'})
また、name
や filename
などを指定したい場合は、set_content_disposition
を使用するようです。
part = mpwriter.append(image, {'Content-Type': 'image/jpeg'})
part.set_content_disposition('form-data', name="name", filename="filename")
JSON を送りたい場合
append_json
に dict 型のデータを渡せばOKです。
mpwriter.append_json({'test': 'passed'})
JSON と画像を一緒に送る例
以前、requests モジュールを使って multipart/form-data
のデータを送る記事を書きました。
これを aiohttp で書いてみたのが以下です。
import asyncio
import aiohttp
from datetime import datetime
async def main():
with aiohttp.MultipartWriter("form-data") as mpwriter:
for camera_id in ['hoge', 'piyo']: # 各カメラのID
# 適当なテキストデータ
json_data = {
'camera_id': camera_id,
'datetime': datetime.now().isoformat()
}
# 適当な画像ファイルを読み込む
image = None
filename = 'send_image.jpg'
with open(filename, 'rb') as f:
image = f.read()
# JSON の追加
part = mpwriter.append_json(json_data)
part.set_content_disposition('form-data', name=camera_id)
# 画像の追加
part = mpwriter.append(image, {'Content-Type': 'image/jpeg'})
part.set_content_disposition('form-data', name=camera_id, filename=camera_id)
# 送信
async with aiohttp.ClientSession() as session:
res = await session.post(f'http://localhost:8000', data=mpwriter)
print(res)
if __name__ == '__main__':
asyncio.run(main())