2013-08-07 5 views
8

Wir versuchen, ein Skript mit Python (mit python-requests a.t.m.) zu schreiben, um eine POST-Anfrage an eine Site zu stellen, deren Inhalt MultipartFormData sein muss. Wenn wir diese POST-Anforderung manuell (durch das Formular auf der Seite und nach Füllung), mit wireshark, kamen diese (Kurzfassung) bis:POST-Anfrage mit Multipart/Formulardaten. Inhaltstyp nicht korrekt

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

Wenn wir versuchen, die Python-Anfragen Bibliothek zu verwenden für das gleiche Ergebnis zu erzielen, wird diese gesendet:

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 

das seltsame ist, dass die ‚allgemeine Art‘ des Pakets in der Tat multipart/form-data, aber die einzelnen Artikel (key = ‚name‘ gesendet, Wert = 'John Doe') hat den Typ application/x-pandoplugin (eine zufällige Anwendung auf meinem PC, denke ich).

Dies ist der Code verwendet:

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

Gibt es einen Weg, um den Inhaltstyp der einzelnen Posten anstelle der Verwendung des Header-Argument (die nur den Typ des ‚ganze‘ Paket ändert) angeben ?

Wir denken, dass der Server nicht richtig reagiert, weil er den Inhaltstyp, den wir senden, nicht verstehen kann.

Kleines Update: denke ich, die verschiedenen Teile des mehrteiliger Inhalte sind jetzt identisch mit denen gesendet, wenn ich die POST im Browser zu tun, so dass gut ist. Trotzdem führt der Server die Änderungen, die ich mit dem Skript gesendet habe, nicht aus. Das einzige, was noch anders ist, ist die Reihenfolge der verschiedenen Teile.

Zum Beispiel ist es das, was mein Browser sendet:

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) 

Und das ist, was das Skript (mit Python-Anfragen) sendet:

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) 

Könnte es möglich sein, dass der Server zählt auf die Reihenfolge der Teile? Nach Multipart upload form: Is order guaranteed? ist es anscheinend? Und wenn ja, ist es möglich, eine Bestellung explizit über die Anfragenbibliothek zu erzwingen? Und um die Dinge in diesem Fall schlimmer zu machen: Es gibt eine Mischung aus einer Datei und nur Textwerte.

So eine Bestellung erzwingt scheint ziemlich schwierig. Dies ist die aktuelle Art, wie ich es tun:

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

EDIT2: ich eine Änderung in den Anforderungen tat Plugin die Reihenfolge der Teile, um sicherzustellen, die gleichen wie in der ursprünglichen Anfrage. Das behebt das Problem nicht, daher denke ich, dass es keine einfache Lösung für mein Problem gibt. Ich werde eine E-Mail an die Entwickler der Seite senden und hoffe, dass sie mir helfen können!

Antwort

7

Ihr Code sieht korrekt aus.

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

... und sollte eine 'multipart/form-data' Post senden.

und in der Tat, ich so etwas wie dies geschrieben:

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-- 

Ich habe keine Ahnung, warum Sie diesen seltsamen Content-Type-Header erhalten würden:

Content-Type: application/x-pandoplugin 

ich anfangen würde durch Entfernen Sie das Pando Web Plugin vollständig von Ihrem Computer und versuchen Sie es dann erneut mit Ihrem Python-Request-Code. (Oder versuchen, von einer anderen Maschine)

+0

Wir sind auf verschiedenen Maschinen versucht. Auf einem anderen war es application/x-uplaypc. Es scheint, als ob zufällige Plugins den Standardinhaltstyp übernehmen. Ich habe auch keine Ahnung, warum das passiert. – HaS

+0

Es ist höchst zweifelhaft, aber ihr Jungs verwenden NETRC tun? –

+0

Nein, nicht dass ich wüsste zumindest. Ich denke, ich habe das Problem fast gelöst, also habe ich mir das aktualisierte Problem angesehen. Da Sie eine Zusammenarbeit für Anfragen sind, kennen Sie vielleicht die Antwort? Danke im Voraus! – HaS

0

Python verwendet eine systemweite Konfigurationsdatei „erraten“ den MIME-Typ einer Datei. Wenn diese Plugins Ihre Dateierweiterung mit ihrem eigenen Pantomime-Typ registrieren, werden Sie dies am Ende tun.

Der sicherste Ansatz ist, dass Sie Ihren eigenen MIME-Typ erraten, der zu dem bestimmten Server passt, den Sie senden, und nur den nativen Python-MIME-Typ für Erweiterungen verwenden, an die Sie nicht gedacht haben.

Wie genau Sie den Content-Typ manuell mit python-Anfragen angeben, weiß ich nicht, aber ich erwarte, sollte es möglich sein.

1

Ab heute können Sie tun:

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