Korrigieren Sie den Multipart / Formulardatenkörper richtig

9

Einführung

Hintergrund

Ich schreibe ein Skript zum Hochladen von Dateien einschließlich Dateien mit dem in RFC 2388 definierten Inhaltstyp multipart/form-data . Auf lange Sicht versuche ich, ein einfaches Python-Skript für Hochladen von Binärpaketen für github , bei dem formularbasierte Daten an Amazon S3 gesendet werden.

Verwandte

Diese Frage hat bereits gefragt, wie dies zu tun ist, aber es ist bisher ohne eine akzeptierte Antwort und < a href="https://stackoverflow.com/a/7064786/1468366"> das nützlichere der beiden Antworten, auf die es aktuell verweist diese Rezepte , die wiederum die ganze Nachricht manuell erstellen. Ich bin etwas besorgt über diesen Ansatz, insbesondere in Bezug auf Zeichensätze und binäre Inhalte.

Es gibt auch diese Frage mit derzeit am besten bewertete Antwort , die das MultipartPostHandler -Modul vorschlägt. Aber das ist nicht viel anders als die Rezepte, die ich erwähnt habe, und deshalb gelten meine Bedenken auch dafür.

Bedenken

Binärer Inhalt

In RFC 2388 Abschnitt 4.3 wird ausdrücklich angegeben, dass der Inhalt 7 Bit beträgt, sofern nicht anders angegeben, und Daher ist möglicherweise ein Header Content-Transfer-Encoding erforderlich. Bedeutet das, dass ich Base64-Binärdateien kodieren müsste? Oder würde Content-Transfer-Encoding: 8bit für beliebige Dateien ausreichen? Oder sollte das Content-Transfer-Encoding: binary ? Lesen?

Zeichensatz für Header-Felder

Kopfzeilenfelder im Allgemeinen und das Kopfzeilenfeld filename im Besonderen sind standardmäßig nur ASCII. Ich möchte, dass meine Methode auch Nicht-ASCII-Dateinamen übergeben kann. Ich weiß, dass ich das für meine aktuelle Anwendung des Hochladens von Zeug für github wahrscheinlich nicht brauchen werde, da der Dateiname in einem separaten Feld angegeben ist. Aber ich möchte, dass mein Code wiederverwendbar ist, daher möchte ich den Parameter Dateiname konform codieren. RFC 2388 Abschnitt 4.4 rät das in RFC 2231 , z filename*=utf-8''t%C3%A4st.txt .

Mein Ansatz

Verwenden von Python-Bibliotheken

Da multipart/form-data im Wesentlichen ein MIME-Typ ist, dachte ich, dass es möglich sein sollte, email zu verwenden. Paket aus den Standard-Python-Bibliotheken, um meinen Beitrag zu verfassen. Die ziemlich komplizierte Handhabung von Nicht-ASCII-Header-Feldern ist etwas, das ich gerne delegieren würde.

Bis jetzt arbeiten

Also habe ich den folgenden Code geschrieben:

%Vor%

Das Ergebnis sieht folgendermaßen aus:

%Vor%

Es scheint Header ziemlich gut zu behandeln. Binärdateiinhalt wird base64-codiert, was vermeidbar sein könnte, aber die gut genug funktionieren sollte. Was mich beunruhigt, sind die Textfelder dazwischen. Sie sind auch Base64-codiert. Ich denke, dass dies nach dem Standard gut funktionieren sollte, aber ich würde lieber reinen Text drin haben, nur für den Fall, dass ein dummes Framework mit den Daten auf einer mittleren Ebene umgehen muss und nichts über Base64-kodierte Daten weiß.

Fragen

  • Kann ich 8-Bit-Daten für meine Textfelder verwenden und trotzdem der Spezifikation entsprechen?
  • Kann ich das E-Mail-Paket dazu bringen, meine Textfelder als 8-Bit-Daten ohne zusätzliche Verschlüsselung zu serialisieren?
  • Wenn ich mich an eine 7-Bit-Codierung halten muss, kann ich die Implementierung dazu bringen, zitierte druckbare Elemente für jene Textteile zu verwenden, wo diese Codierung kürzer ist als base64?
  • Kann ich die base64-Kodierung für Binärdateien auch vermeiden?
  • Wenn ich es vermeiden kann, sollte ich die Content-Transfer-Encoding als 8bit oder als binary ?
  • schreiben
  • Wenn ich den Körper selbst serialisieren müsste, wie könnte ich das email.header -Paket allein um Header-Werte zu formatieren? ( email.utils.encode_rfc2231 tut das.)
  • Gibt es eine Implementierung, die bereits alles getan hat, was ich versuche?

Diese Fragen sind sehr eng miteinander verknüpft und könnten als "wie würden Sie das umsetzen" zusammengefasst werden. In vielen Fällen beantwortet oder beantwortet eine Frage eine andere Frage. Also ich hoffe, Sie stimmen zu, dass ein einziger Beitrag für alle von ihnen angemessen ist.

    
MvG 22.11.2012, 14:24
quelle

2 Antworten

2

Dies ist eine Platzhalterantwort, die beschreibt, was ich getan habe, während ich auf einige autoritative Eingaben zu einigen meiner Fragen gewartet habe. Ich bin froh, eine andere Antwort zu akzeptieren, wenn es zeigt, dass dieser Ansatz in mindestens einer der Designentscheidungen falsch oder ungeeignet ist.

Hier ist der Code, den ich verwendet habe, um diese Arbeit gemäß meiner zu machen Geschmack für jetzt. Ich habe folgende Entscheidungen getroffen:

  

Kann ich 8-Bit-Daten für meine Textfelder verwenden und trotzdem der Spezifikation entsprechen?

Ich habe mich dazu entschieden. Zumindest für diese Anwendung funktioniert es.

  

Kann ich mit dem E-Mail-Paket meine Textfelder als 8-Bit-Daten ohne zusätzliche Codierung serialisieren?

Ich habe keinen Weg gefunden, also mache ich meine eigene Serialisierung, genau wie all die andere Rezepte habe ich gesehen.

  

Kann ich die base64-Kodierung für Binärdateien auch vermeiden?

Das Senden des Dateiinhalts in Binärdateien scheint zumindest in meiner einzigen Anwendung gut genug zu funktionieren.

  

Wenn ich es vermeiden kann, sollte ich das Content-Transfer-Encoding als 8bit oder als Binär schreiben?

Wie in RFC 2045 Section 2.8 heißt es, dass 8bit data einer Zeilenlängenbeschränkung unterliegt von 998 Oktetts zwischen CRLF-Paaren habe ich entschieden, dass binary die allgemeinere und somit die passendere Beschreibung hier ist.

  

Wenn ich den Körper selbst serialisieren müsste, wie könnte ich das email.header-Paket allein dazu verwenden, Header-Werte einfach zu formatieren?

Wie bereits in meiner Frage bearbeitet, ist email.utils.encode_rfc2231 sehr nützlich dafür. Ich versuche, Ascii zuerst zu kodieren, aber benutze diese Methode im Falle von Nicht-Ascii-Daten oder Ascii-Zeichen, die in einer doppelten Anführungszeichen verboten sind.

  

Gibt es eine Implementierung, die bereits alles getan hat, was ich versuche?

Nicht dass ich mir dessen bewusst bin. Andere Implementierungen werden aufgefordert, Ideen aus meinem Code zu übernehmen.

>

Bearbeiten:

Dank diesem Kommentar ist mir jetzt bewusst, dass RFC 2231 für Header verwendet wird ist nicht allgemein akzeptiert: Der aktuelle Entwurf von HTML 5 verbietet seine Verwendung . Es wurde auch gesehen, Probleme in der Wildnis zu verursachen . Aber da POST-Header nicht immer einem bestimmten HTML-Dokument entsprechen (denke zum Beispiel an Web-APIs), bin ich mir nicht sicher, ob ich diesem Entwurf auch in dieser Hinsicht vertrauen würde. Vielleicht ist der richtige Weg zu gehen, geben Sie sowohl codiert als auch uncodiert Name, die Art und Weise RFC 5987 Abschnitt 4.2 schlägt vor. Aber dieser RFC ist für HTTP-Header, während ein Multipart / Form-Data-Header technisch HTTP-Körper ist. Dieser RFC gilt daher nicht, und ich kenne keinen RFC, der explizit die Verwendung beider Formulare gleichzeitig für Multipart / Form-Daten erlauben würde (oder sogar ermutigen könnte).

    
MvG 23.11.2012, 22:18
quelle
1

Sie können sich die Datei mit POST von einem Python-Skript aus ansehen, die auf Anfragen Bibliothek, die die am häufigsten verwendete Python-Bibliothek für http wird. Falls Sie dort nicht alle benötigten Funktionen finden und sich für die Implementierung entscheiden, ermutige ich Sie dazu, sich an diesem Projekt zu beteiligen.

    
Piotr Dobrogost 22.11.2012 19:01
quelle