Pythonでmultipart/form-data
withを送信するには? requests
ファイルの送信方法はわかりましたが、この方法でフォームデータを送信する方法がわかりません。
13 に答える
基本的に、files
パラメータ (辞書)を指定すると、 POST の代わりに POSTrequests
が送信されます。ただし、そのディクショナリ内の実際のファイルを使用することに限定されません。multipart/form-data
application/x-www-form-urlencoded
>>> import requests
>>> response = requests.post('http://httpbin.org/post', files=dict(foo='bar'))
>>> response.status_code
200
また、httpbin.org では、投稿したヘッダーを知ることができます。私たちはresponse.json()
持っています:
>>> from pprint import pprint
>>> pprint(response.json()['headers'])
{'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'close',
'Content-Length': '141',
'Content-Type': 'multipart/form-data; '
'boundary=c7cbfdd911b4e720f1dd8f479c50bc7f',
'Host': 'httpbin.org',
'User-Agent': 'python-requests/2.21.0'}
さらに良いことに、単一の文字列またはバイト オブジェクトの代わりにタプルを使用して、各パーツのファイル名、コンテンツ タイプ、および追加のヘッダーをさらに制御できます。タプルには 2 ~ 4 個の要素が含まれていると予想されます。ファイル名、コンテンツ、オプションのコンテンツ タイプ、オプションの追加ヘッダーの辞書。
これらの部分のリクエストからパラメーターが削除されるNone
ように、ファイル名としてタプル形式を使用します。filename="..."
>>> files = {'foo': 'bar'}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--bb3f05a247b43eede27a124ef8b968c5
Content-Disposition: form-data; name="foo"; filename="foo"
bar
--bb3f05a247b43eede27a124ef8b968c5--
>>> files = {'foo': (None, 'bar')}
>>> print(requests.Request('POST', 'http://httpbin.org/post', files=files).prepare().body.decode('utf8'))
--d5ca8c90a869c5ae31f70fa3ddb23c76
Content-Disposition: form-data; name="foo"
bar
--d5ca8c90a869c5ae31f70fa3ddb23c76--
files
順序付けや同じ名前の複数のフィールドが必要な場合は、2 つの値のタプルのリストにすることもできます。
requests.post(
'http://requestb.in/xucj9exu',
files=(
('foo', (None, 'bar')),
('foo', (None, 'baz')),
('spam', (None, 'eggs')),
)
)
と の両方を指定する場合はfiles
、POST 本文の作成に使用されるものの値によってdata
異なります。が文字列の場合、それのみが使用されます。それ以外の場合は、との両方が使用され、 の要素が最初にリストされます。data
data
data
files
data
高度なマルチパート サポートrequests-toolbelt
を含む優れたプロジェクトもあります。パラメータと同じフォーマットでフィールド定義を取りますが、 とは異なり、デフォルトでファイル名パラメータを設定しません。さらに、開いているファイル オブジェクトからリクエストをストリーミングできます。ここで、最初にメモリ内にリクエスト ボディを構築します。files
requests
requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
mp_encoder = MultipartEncoder(
fields={
'foo': 'bar',
# plain file object, no filename or mime type produces a
# Content-Disposition header with just the part name
'spam': ('spam.txt', open('spam.txt', 'rb'), 'text/plain'),
}
)
r = requests.post(
'http://httpbin.org/post',
data=mp_encoder, # The MultipartEncoder is posted as data, don't use files=...!
# The MultipartEncoder provides the content-type header with the boundary:
headers={'Content-Type': mp_encoder.content_type}
)
フィールドは同じ規則に従います。2 ~ 4 個の要素を持つタプルを使用して、ファイル名、一部の MIME タイプ、または追加のヘッダーを追加します。パラメータとは異なり、タプルを使用しない場合files
、デフォルト値を見つける試みは行われません。filename
以前の回答のいくつかが書かれてから、リクエストが変更されました。詳細については、Github のこの問題を参照してください。例については、このコメントを参照してください。
つまり、files
パラメーターは、キーがフォーム フィールドの名前で、値が文字列または長さ 2、3、または 4 のタプルのいずれかであるディクショナリを取ります。クイックスタート:
>>> url = 'http://httpbin.org/post'
>>> files = {'file': ('report.xls', open('report.xls', 'rb'), 'application/vnd.ms-excel', {'Expires': '0'})}
上記では、タプルは次のように構成されます。
(filename, data, content_type, headers)
値が単なる文字列の場合、ファイル名は次のようにキーと同じになります。
>>> files = {'obvius_session_id': '72c2b6f406cdabd578c5fd7598557c52'}
Content-Disposition: form-data; name="obvius_session_id"; filename="obvius_session_id"
Content-Type: application/octet-stream
72c2b6f406cdabd578c5fd7598557c52
値がタプルで、最初のエントリがNone
filename プロパティである場合、含まれません:
>>> files = {'obvius_session_id': (None, '72c2b6f406cdabd578c5fd7598557c52')}
Content-Disposition: form-data; name="obvius_session_id"
Content-Type: application/octet-stream
72c2b6f406cdabd578c5fd7598557c52
以下は、リクエストを使用して追加のパラメーターを含む 1 つのファイルをアップロードするための簡単なコード スニペットです。
url = 'https://<file_upload_url>'
fp = '/Users/jainik/Desktop/data.csv'
files = {'file': open(fp, 'rb')}
payload = {'file_id': '1234'}
response = requests.put(url, files=files, data=payload, verify=False)
コンテンツ タイプを明示的に指定する必要はないことに注意してください。
注: 上記の回答のいずれかにコメントしたかったのですが、評判が低いためにコメントできなかったため、ここに新しい回答を作成しました。
これは、マルチパート リクエストでファイルを送信する 1 つの方法です。
import requests
headers = {"Authorization": "Bearer <token>"}
myfile = 'file.txt'
myfile2 = {'file': (myfile, open(myfile, 'rb'),'application/octet-stream')}
url = 'https://example.com/path'
r = requests.post(url, files=myfile2, headers=headers,verify=False)
print(r.content)
その他のアプローチ
import requests
url = "https://example.com/path"
payload={}
files=[
('file',('file',open('/path/to/file','rb'),'application/octet-stream'))
]
headers = {
'Authorization': 'Bearer <token>'
}
response = requests.request("POST", url, headers=headers, data=payload, files=files)
print(response.text)
私は両方をテストしましたが、両方とも正常に動作します。
Python 3のリクエストモジュールを使用してURL_serverにリクエストを送信しようとしています.これは私にとってはうまくいきます:
# -*- coding: utf-8 *-*
import json, requests
URL_SERVER_TO_POST_DATA = "URL_to_send_POST_request"
HEADERS = {"Content-Type" : "multipart/form-data;"}
def getPointsCC_Function():
file_data = {
'var1': (None, "valueOfYourVariable_1"),
'var2': (None, "valueOfYourVariable_2")
}
try:
resElastic = requests.post(URL_GET_BALANCE, files=file_data)
res = resElastic.json()
except Exception as e:
print(e)
print (json.dumps(res, indent=4, sort_keys=True))
getPointsCC_Function()
どこ:
- URL_SERVER_TO_POST_DATA = データを送信するサーバー
- HEADERS = 送信されたヘッダー
- file_data = パラメータが送信されました