Python

【Python】【Requests】multipart/form-dataで値データのみを送信する

APIでPOSTリクエストをする際に、Content-Typeとしてmultipart/form-dataで送信する必要がある場合がある。

通常、multipart/form-dataは画像やCSVなどのファイルを送信する際に使用されるが、画像ファイルなどはなしで値のみを送信したい場合もある。

画像と値を合わせて送信したい場合、filesとdataを指定すれば良い感じに送信してくれるが、値データだけを送信したい場合、少し特殊になる。

値データのみをmultipart/form-dataで送信①

filesのみに値データを設定して送信する。dataは使用しないパターン。

import requests

url = "https://sample.com"
files = {
    "key1": (None, "val1"),
    "key2": (None, "val2"),
    "key3": (None, "val3"),
}
r = requests.post(url=url, files=files)
print(f"{r.request.headers}")
{'User-Agent': 'python-requests/2.27.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '1024', 'Content-Type': 'multipart/form-data; boundary=bc7543bf1249b2e58f32c30dfe34d365'}

postパラメータにfilesを指定することで、requestsがboundaryを自動で設定してくれる。

値データのみをmultipart/form-dataで送信②

dataに値を設定し、filesにはNoneを指定するパターン。

import requests

url = "https://sample.com"
data = {
    "key1": "val1",
    "key2": "val2",
    "key3": "val3",
}
files = {(None, None)}

r = requests.post(url=url, data=data, files=files)
print(f"{r.request.headers}")
{'User-Agent': 'python-requests/2.27.1', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'Content-Length': '1024', 'Content-Type': 'multipart/form-data; boundary=bc7543bf1249b2e58f32c30dfe34d365'}

こちらの書き方の方が通常のdata、filesの使い方に似ているので分かりやすいかもしれない。

Content-Typeにmultipart/form-dataを設定するパターン(エラー)

なお、headerのContent-Typeにmultipart/form-dataを設定し、boundaryを設定しなかった場合、boundaryが設定されていない旨のエラーが発生する。

import requests

headers = {"Content-Type": "multipart/form-data"}
url = "https://sample.com"
data = {
    "key1": "val1",
    "key2": "val2",
    "key3": "val3",
}
r = requests.post(url=url, data=data, headers=headers)
print(f"{r.text}")
no multipart boundary param in Content-Type

boundaryを自分で設定できない場合、filesを使用した方が無難。

textやjson形式でデータを送信

application/jsonやapplication/textでデータを送信したい場合は以下の記事を参照。