web-dev-qa-db-ja.com

POST Multipart / form-dataを使用したリクエスト。コンテンツタイプが正しくありません

python(python-requests atmを使用)でスクリプトを記述して、POSTコンテンツがMultipartFormDataである必要があるサイトにリクエストを送信します。POSTリクエストを手動で(サイトのフォームに入力して投稿することにより)、wiresharkを使用して実行すると、これが表示されます(短いバージョン):

Content-Type: multipart/form-data;
Content-Disposition: form-data; name="name"
Data (8 Bytes)
    John Doe

同じ結果を得るためにpython-requestsライブラリを使用しようとすると、これが送信されます。

Content-Type: application/x-pandoplugin
Content-Disposition: form-data; name="name"; filename="name"\r\n
Media type: application/x-pandoplugin (12 Bytes)
    //and then in this piece is what we posted://
    John Doe

奇妙なことに、パケットの「一般的なタイプ」は確かにmultipart/form-dataですが、送信された個々のアイテム(key = 'name'、value = 'John Doe')のタイプはapplication/x-pandoplugin(ランダム私のPCでのアプリケーション)。

これは使用されるコードです:

response = s.post('http://url.com', files={'name': 'John Doe'})

Headers引数(「パケット全体」のタイプのみを変更する)を使用する代わりに、個々のアイテムのコンテンツタイプを指定する方法はありますか?

サーバーは、送信するコンテンツタイプを理解できないため、サーバーが正しく応答しないと考えています。

小さな更新:マルチパートコンテンツのさまざまな部分は、POST =ブラウザーでは、それでいいのですが、サーバーが実際にスクリプトで送信した変更を実際に行うわけではありません。まだ異なるのは、異なる部分の順序だけです。

たとえば、これは私のブラウザが送信するものです:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

そして、これは(python-requestsを使用した)スクリプトが送信するものです:

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="name"\r\n\r\n
    Data (2 bytes)

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part:  (text/plain)
    Content-Disposition: form-data; name="file"; filename="ex.txt"\r\n
    Content-Type: text/plain\r\n\r\n
    Line-based text data: text/plain
        lore ipsum blabbla

Boundary: \r\n------WebKitFormBoundary3eXDYO1lG8Pgxjwj\r\n
Encapsulated multipart part: 
    Content-Disposition: form-data; name="seq"\r\n\r\n
    Data (2 bytes)

サーバーがパーツの注文に依存している可能性はありますか? マルチパートアップロードフォーム:順序は保証されますか? によると、それはどうですか?もしそうなら、リクエストライブラリを使用して注文を明示的に強制することは可能ですか?そして、その場合に事態をさらに悪化させるために、ファイルと単なるテキスト値が混在しています。

したがって、注文を強制することはかなり難しいようです。これは私が現在行う方法です:

s.post('http://www.url.com', files=files,data = form_values)

EDIT2:パーツの順序が元のリクエストと同じになるように、リクエストプラグインを変更しました。これは問題を解決しないので、私の問題に対する簡単な解決策はないと思います。私はサイトの開発者にメールを送り、彼らが私を助けてくれることを願っています!

10
HaS

あなたのコードは正しいようです。

requests.post('http://url.com', files={'name': 'John Doe'})

...そして 'multipart/form-data' Postを送信する必要があります。

そして確かに、私はこのようなものを投稿しました:

Accept-Encoding: gzip, deflate, compress
Connection: close
Accept: */*
Content-Length: 188
Content-Type: multipart/form-data; boundary=032a1ab685934650abbe059cb45d6ff3
User-Agent: python-requests/1.2.3 CPython/2.7.4 Linux/3.8.0-27-generic

--032a1ab685934650abbe059cb45d6ff3
Content-Disposition: form-data; name="name"; filename="name"
Content-Type: application/octet-stream

John Doe
--032a1ab685934650abbe059cb45d6ff3--

私にはnoがあり、なぜ奇妙なContent-Typeヘッダーが表示されるのかを理解しています。

Content-Type: application/x-pandoplugin

まず、マシンからPando Webプラグインを完全に削除してから、python-requestsコードを再試行します。 (または別のマシンから試してください)

8
Corey Goldberg

今日からできること:

response = s.post('http://url.com', files={'name': (filename, contents, content_type)})
2
pguardiario

Pythonはシステム全体の構成ファイルを使用して、ファイルのMIMEタイプを「推測」します。それらのプラグインがファイル拡張子をカスタムのMIMEタイプに登録している場合は、代わりにそれを挿入することになります。

最も安全な方法は、送信する特定のサーバーに適した独自のMIMEタイプを推測させ、考えていなかった拡張子に対してのみネイティブのpython MIMEタイプを推測させることです。

どのように正確にpython-requestsを使用してcontent-typeを手動で指定するかはわかりませんが、それが可能になるはずです。

0