Ich lade eine Datei mit der get
Funktion von Python requests
Bibliothek. Um die Datei zu speichern, möchte ich den Dateinamen so festlegen, wie ein Webbrowser ihn speichern oder speichern würde.Wie ermittelt man den Dateinamen von Inhalten, die mit HTTP in Python heruntergeladen werden?
Einfach, oder? Ich kann es einfach get it from the Content-Disposition
HTTP-Header, zugänglich auf dem Antwortobjekt:
import re
d = r.headers['content-disposition']
fname = re.findall("filename=(.+)", d)
Aber genaueres Hinsehen zu diesem Thema, es ist nicht dass einfach:
Nach RFC 6266 section 4.3 und der Grammatik in der section 4.1 kann der Wert ein Token ohne Anführungszeichen sein (z. B. the_report.pdf
) oder eine Zeichenfolge in Anführungszeichen, die auch Leerzeichen (z. B. "the report.pdf"
) und Escape-Sequenzen enthalten kann. Weiter,
Wenn sowohl "Dateiname" und "Dateiname *" in einem einzigen Header-Feld Wert vorhanden sind, sollten wir wählen "Dateiname *" und ignorieren "Dateiname".
Der Wert von filename*
ist jedoch, yet a bit more complicated als die von filename
.
Auch der RFC scheint zusätzliche Whitespace um die zu ermöglichen.
So ist für die examples listed in the RFC, würde ich folgende Ergebnisse wollen:
Dateiname:Content-Disposition: Attachment; filename=example.html
example.html
Dateiname:Content-Disposition: INLINE; FILENAME= "an example.html"
an example.html
Dateiname:Content-Disposition: attachment; filename*= UTF-8''%e2%82%ac%20rates
€ rates
Dateiname:Content-Disposition: attachment; filename="EURO rates"; filename*=utf-8''%e2%82%ac%20rates
€ rates
hier auch (nichtEURO rates
, wiefilename*
Vorrang) Jetzt
, konnte ich einfach den regulären Ausdruck passen um die =
, für variable Leerzeichen zu berücksichtigen, sondern mit damit umgehen auch alle anderen Variationen würden ziemlich unhandlich werden. (Mit dem Zitat und Flucht, ich bin nicht einmal sicher, RegEx kann alle Fälle decken. Vielleicht können sie, da es keine Klammerverschachtelung beteiligt ist.)
Also muss ich einen ausgewachsenen Parser implementieren oder kann ich Dateinamen nach RFC 6266 durch einige wenige Aufrufe an eine HTTP-Bibliothek (vielleicht requests
selbst) bestimmen? Da RFC 6266 Teil des HTTP-Standards ist, könnte ich mir vorstellen, dass einige auf HTTP spezialisierte Bibliotheken dies bereits abdecken. (So habe ich also asked on Software Recommendations SE.)
Was meinen Sie mit "nicht standardmäßigen Leerzeichen"? Leerzeichen an Stellen, an denen der Standard keine Leerzeichen erlaubt? Oder UNICODE-Leerzeichen, die nicht Teil von 7-Bit-ASCII sind? –
@ das-g Habe nicht genug untersucht, um es dir zu sagen. Es stellt sich heraus, dass "parse_headers" eine "entspannte" Option hat, die dabei hilft. Sehen Sie sich den Code [hier] an (https://github.com/g2p/rfc6266/blob/master/rfc6266.py#L209). – Kupiakos