web-dev-qa-db-de.com

POST Anfrage mit Multipart/Formulardaten. Inhaltstyp nicht korrekt

Wir versuchen, ein Skript mit Python (mit Python-Requests a.t.m.) zu schreiben, um eine POST -Anforderung an eine Site zu senden, auf der der Inhalt MultipartFormData sein muss. Wenn wir diese POST -Anfrage manuell (durch Ausfüllen des Formulars auf der Website und im Posting) mit Wireshark ausführen, kam dies (kurze Version):

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

Wenn wir versuchen, die Python-Request-Bibliothek zu verwenden, um dasselbe Ergebnis zu erzielen, wird Folgendes 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 der 'allgemeine Typ' des Pakets tatsächlich Multipart-/Formulardaten ist, aber das einzelne gesendete Element (Schlüssel = 'Name', Wert = 'John Doe') hat den Typ 'application/x-pandoplugin' (zufällig) Anwendung auf meinem PC, denke ich).

Dies ist der verwendete Code:

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

Gibt es eine Möglichkeit, den Inhaltstyp der einzelnen Elemente anzugeben, anstatt das Argument headers zu verwenden (wodurch nur der Typ des gesamten Pakets geändert wird)?

Wir glauben, dass der Server nicht korrekt reagiert, da er den Inhaltstyp, den wir ihm senden, nicht verstehen kann.

Kleines Update: Ich denke, die verschiedenen Teile des Multipart-Inhalts sind jetzt identisch mit denen, die gesendet werden, wenn ich den POST im Browser mache. Das ist also gut. Der Server nimmt die Änderungen, die ich mit dem Skript versende, trotzdem nicht vor. Das einzige, was noch anders ist, ist die Reihenfolge der verschiedenen Teile. 

Zum Beispiel sendet dies mein Browser: 

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)

Kann es sein, dass der Server auf die Reihenfolge der Teile zählt? Gemäß Multipart-Upload-Formular: Ist die Bestellung garantiert? , ist es anscheinend? Und wenn ja, ist es möglich, eine Bestellung explizit mit Hilfe der Anforderungsbibliothek zu erzwingen? Und um das Ganze noch zu verschlimmern: Es gibt eine Mischung aus einer Datei und nur Textwerten.

Es ist also ziemlich schwierig, eine Bestellung zu erzwingen. So mache ich es aktuell:

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

EDIT2: Ich habe im Requests-Plugin eine Änderung vorgenommen, um sicherzustellen, dass die Reihenfolge der Teile dieselbe ist wie in der ursprünglichen Anfrage. Das Problem wird dadurch nicht behoben. Ich denke, es gibt keine einfache Lösung für mein Problem. Ich schicke eine Mail an die Entwickler der Website und hoffe, dass sie mir helfen können!

8
HaS

ihr Code sieht korrekt aus.

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

... und soll einen 'Multipart/Form-Daten'-Beitrag schicken.

und in der Tat bekomme ich so etwas 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 nein eine Idee, warum Sie diesen seltsamen Content-Type-Header erhalten würden:

Content-Type: application/x-pandoplugin

Ich würde damit beginnen, das Pando Web Plugin vollständig von Ihrem Computer zu entfernen und dann Ihren Python-Request-Code erneut zu testen. (oder von einem anderen Rechner aus versuchen)

8
Corey Goldberg

Ab heute können Sie:

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

Python verwendet eine systemweite Konfigurationsdatei, um den Mime-Typ einer Datei zu erraten. Wenn diese Plugins Ihre Dateierweiterung mit ihrem benutzerdefinierten Mime-Typ registrieren, setzen Sie diese stattdessen ein.

Am sichersten ist es, Ihren eigenen Mime-Typ zu schätzen, der zu dem jeweiligen Server passt, den Sie senden, und nur den nativen Python-Mime-Typ für Erweiterungen zu verwenden, an die Sie nicht gedacht haben.

Wie genau Sie den Inhaltstyp manuell mit Python-Anforderungen angeben, weiß ich nicht, aber ich gehe davon aus, dass dies möglich sein sollte.

0