2
1

More than 3 years have passed since last update.

Python Requestsを使ってmultipart/form-dataをin-memoryで送る方法

Last updated at Posted at 2021-08-21

概要

Python Requestsを使って、multipart/form-dataを送る場合、openで開いたファイルを送る仕様となっている。
Pythonの辞書形式のデータをJSONファイルとして送る場合、一時的にJSONファイルを作成せずに送る方法が分からなかった。
Python Requestsを使ってmultipart/form-dataをin-memoryで送る方法を記す。

Python Requestsの仕様

Python Requestsを使って、multipart/form-dataを送る場合、openで開いたファイルを送る仕様となっている。
https://requests-docs-ja.readthedocs.io/en/latest/user/quickstart/#id7

import requests

url = "https://example.com"
headers = {
  "Content-Type": "multipart/form-data",
}
files = {
  'file': ('report.xls', open('report.xls', 'rb'))
}
response = requests.post(url, headers=headers, files=files)

解決方法

JSON(辞書データ)を送りたい場合

from io import BytesIO
import json
import requests

url = "https://example.com"
data = {"hoge":"hoge"}
headers = {
  "Content-Type": "multipart/form-data",
}

binary_stream = BytesIO(json.dumps(data).encode('utf-8'))
files = {
  "file": ("filename.json", binary_stream),
}
response = requests.post(url, headers=headers, files=files)

解説

open で何を呼び出しているかというと、バイナリストリームのオブジェクトである。
ioのリファレンスを読むと以下のように書いてある。
https://docs.python.org/ja/3/library/io.html#module-io

バイナリー I/O (buffered I/O とも呼ばれます) は bytes-like オブジェクト を受け取り bytes オブジェクトを生成します。エンコード、デコード、改行文字変換は一切行いません。このカテゴリのストリームは全ての非テキストデータや、テキストデータの扱いを手動で管理したい場合に利用することができます。

バイナリーストリームを生成する一番簡単な方法は、 open() の mode 文字列に 'b' を指定することです:

f = open("myfile.jpg", "rb")
BytesIO はインメモリーのバイナリストリームです:

f = io.BytesIO(b"some initial binary data: \x00\x01")
バイナリーストリーム API は BufferedIOBase のドキュメントで詳しく解説します。

ということで、open()でファイルからバイナリストリームオブジェクトを生成する代わりに、io.BytesIO()でインメモリのバイナリストリームを生成する。

辞書データからバイナリストリームまでの道のり

from io import BytesIO
import json

# 元なる辞書
data = {"hoge":"hoge"} 
# JSONとして、Stringに変換
string_data = json.dumps(data) 
# utf-8形式でバイトに変換、
bytes_data = string_data.encode('utf-8')
# バイトデータをバイナリストリームに変換 
binary_stream = BytesIO(bytes_data)

もちろん、JSON以外にCSVやXMLなどもインメモリで作成し、そのまま requestsmultipart/form-dataとして送ることが可能。

参考記事

辞書データをJSONに変換し、BytesIOオブジェクトにする方法の参考にした。
https://stackoverflow.com/questions/53118672/what-is-correct-way-to-load-json-file-stored-in-the-bytesio-object
openBytesIO オブジェクトの違いについて参考にした。
https://stackoverflow.com/questions/42800250/difference-between-open-and-io-bytesio-in-binary-streams

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1