質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

2回答

4140閲覧

【Python】 requestsで画像POSTすると400エラー

QueueuQ

総合スコア15

HTTP

HTTP(Hypertext Transfer Protocol)とはweb上でHTML等のコンテンツを交換するために使われるアプリケーション層の通信プロトコルです。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2020/07/13 14:53

問題の概要

ローカルホストでオブジェクト検出のAPIサーバーを立てています(画像をPOSTすると画像に写っているオブジェクトを検出してテキストデータで返してくれる)。そこにPythonからrequestsを使って画像をPOSTして返り値を見たいのですが、400エラーになってしまいます。

該当のコード

python

1import requests 2 3url = 'http://localhost:5000/model/predictor' 4files = {'image': open('imagepath/img.jpg', 'rb')} 5res = requests.post(url, files=files) 6 7print(res) 8print(res.reason) 9print(res.text)

この結果

<Response [400]> BAD_REQUEST '{"message": "Invalid file type/extension. Please provide an image in JPEG or PNG format."}\n'

試したこと

ちなみになぜか以下のcurlコマンドだと通ります。

bash

1$ curl -F "image=@imagepath/img.jpg" -X POST http://localhost:5000/model/predictor

curlコマンドをrequestsでの形式に直してくれるサイトを使ってみましたが、それでもダメでした。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

curlコマンドでOKであるならば、curlコマンドでのHTTPリクエストをなるべく真似れば良いはずです。ご提示のcurlコマンドのHTTPリクエストをncコマンドで待ち受けて見てみると、以下のようになります。分かりやすく、img.jpgファイルはダミーのものにしておきます。

bash

1ls -l imagepath/img.jpg 2-rwxrwxrwx 1 user01 user01 30 Jul 14 12:28 imagepath/img.jpg 3$ cat imagepath/img.jpg 4123456789 5123456789 6123456789 7$ 8 9$ nc -l 5000 10POST /model/predictor HTTP/1.1 11Host: localhost:5000 12User-Agent: curl/7.58.0 13Accept: */* 14Content-Length: 216 15Content-Type: multipart/form-data; boundary=------------------------cc991f1cdd79fdee 16 17--------------------------cc991f1cdd79fdee 18Content-Disposition: form-data; name="image"; filename="img.jpg" 19Content-Type: image/jpeg 20 21123456789 22123456789 23123456789 24 25--------------------------cc991f1cdd79fdee--

MIMEのマルチパートの部分で、Content-Type: image/jpeg があるのが分かります。質問者さんのオリジナルのPython3コードでは、この部分が存在しませんでした。ですので、Content-Type: image/jpegを追加するようにコードを修正します。

Python3

1import requests 2 3url = 'http://localhost:5000/model/predictor' 4 5file_data = open('imagepath/img.jpg', 'rb').read() 6files = {'image': ('img.jpg', file_data, 'image/jpeg')} 7res = requests.post(url, files=files) 8 9print(res) 10print(res.reason) 11print(res.text) 12

このPython3スクリプトを実行すると、Content-Type: image/jpeg が追加され、curl実行時のものとほぼ等価になります。

$ nc -l 5000 POST /model/predictor HTTP/1.1 Host: localhost:5000 User-Agent: python-requests/2.18.4 Accept-Encoding: gzip, deflate Accept: */* Connection: keep-alive Content-Length: 200 Content-Type: multipart/form-data; boundary=de917b72bc0d4b31b4df7adb786a3c8f --de917b72bc0d4b31b4df7adb786a3c8f Content-Disposition: form-data; name="image"; filename="img.jpg" Content-Type: image/jpeg 123456789 123456789 123456789 --de917b72bc0d4b31b4df7adb786a3c8f--

これでもまだ問題が解決しないのであれば、もう少しHTTPリクエストのヘッダーフィールドやマルチパート部分を修正する必要があるかと思います。

投稿2020/07/14 03:49

編集2020/07/14 03:51
dodox86

総合スコア9256

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

QueueuQ

2020/07/14 04:15

ありがとうございます。 どうやら'image/jpeg'を指定していなかったのが原因のようでした。
guest

0

提示コードの送信データはデータ(バイナリ)のみで、ファイル種別に関する情報が含まれていません。
そのために提示エラーが発生しているようです。
実際のサーバー側の動作が不明ですが
files = {'file': ('image.jpg', open('imagepath/img.jpg', 'rb'))}
のように、ファイル名(拡張子)を含めてみてはいかがでしょうか?
参考:マルチパートエンコードされたファイルのPOST

投稿2020/07/13 23:02

can110

総合スコア38341

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

QueueuQ

2020/07/13 23:21

files = {'file': ('surfing.jpg', open('./samples/surfing.jpg', 'rb'))} として実行してみましたが、今度は405エラーが出てしまいました。
can110

2020/07/13 23:23

サーバ側の動作が不明なので、詳細、コードを提示すると他にも回答得られるかもしれません。
QueueuQ

2020/07/14 04:13

すいません、事情によりサーバ側のことは申し上げられません。 しかし、新しく回答していただいた方の解法を試したところうまくいきました。 ご意見くださりありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問