Web - Anwendungen , die eine Ressource erzwingen wollen werden heruntergeladen , anstatt direkt gerendert in einem Web - Browser eine Ausgabe - Content-Disposition
Header in der HTTP - Antwort in der Form:
Content-Disposition: attachment; filename=FILENAME
Mit dem filename
Parameter kann ein Name für die Datei vorgeschlagen werden, in die die Ressource vom Browser heruntergeladen wird. In RFC 2183 (Content-Disposition) heißt es jedoch in Abschnitt 2.3 (Der Dateinamenparameter), dass der Dateiname nur US-ASCII-Zeichen verwenden darf:
Die aktuelle Grammatik [RFC 2045] beschränkt die Parameterwerte (und damit die Dateinamen der Inhaltsdisposition) auf US-ASCII. Wir erkennen an, dass es sehr wünschenswert ist, beliebige Zeichensätze in Dateinamen zuzulassen, aber es liegt außerhalb des Rahmens dieses Dokuments, die erforderlichen Mechanismen zu definieren.
Es gibt jedoch empirische Beweise dafür, dass die meisten gängigen Webbrowser heutzutage Nicht-US-ASCII-Zeichen zulassen, sich jedoch (mangels eines Standards) nicht über das Codierungsschema und die Zeichensatzspezifikation des Dateinamens einig sind. Die Frage ist dann, welche verschiedenen Schemata und Codierungen von den gängigen Browsern verwendet werden, wenn der Dateiname "naive Datei" (ohne Anführungszeichen und mit dem dritten Buchstaben U + 00EF) in den Content-Disposition-Header codiert werden muss.
Für die Zwecke dieser Frage sind beliebte Browser :
- Feuerfuchs
- Internet Explorer
- Safari
- Google Chrome
- Oper
quelle
Content-Disposition: attachment
.Antworten:
Dies wird im vorgeschlagenen RFC 5987 "Zeichensatz- und Sprachcodierung für HTTP-Header-Feldparameter (Hypertext Transfer Protocol)" diskutiert, einschließlich Links zu Browsertests und Abwärtskompatibilität .
RFC 2183 gibt an, dass solche Header gemäß RFC 2184 codiert werden sollten , der durch RFC 2231 , der durch den obigen RFC-Entwurf abgedeckt ist , überholt wurde .
quelle
Content-Disposition: filename="foo, bar.pdf"
. Das Ergebnis ist, dass Firefox die Datei korrekt herunterlädt, aber die.part
Erweiterung beibehält (zfoo,bar.pdf-1.part
. B. ). Dann wird die Datei natürlich nicht richtig geöffnet, da die Anwendung nicht zugeordnet ist.part
. Andere ASCII-Zeichen scheinen in Ordnung zu sein.Ich weiß, dass dies ein alter Beitrag ist, aber er ist immer noch sehr relevant. Ich habe festgestellt, dass moderne Browser rfc5987 unterstützen, was eine utf-8-Codierung in Prozent (url-codiert) ermöglicht. Dann wird Naive Datei.txt:
Safari (5) unterstützt dies nicht. Stattdessen sollten Sie den Safari-Standard verwenden, um den Dateinamen direkt in Ihren utf-8-codierten Header zu schreiben:
IE8 und älter unterstützen es ebenfalls nicht und Sie müssen den IE-Standard der utf-8-Codierung verwenden, prozentual codiert:
In ASP.Net verwende ich den folgenden Code:
Ich habe das oben genannte mit IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5 getestet.
Update November 2013:
Hier ist der Code, den ich derzeit verwende. Ich muss IE8 noch unterstützen, damit ich den ersten Teil nicht loswerden kann. Es stellt sich heraus, dass Browser unter Android den integrierten Android-Download-Manager verwenden und Dateinamen nicht auf die übliche Weise zuverlässig analysieren können.
Die oben genannten Tests wurden jetzt in IE7-11, Chrome 32, Opera 12, FF25, Safari 6 unter Verwendung dieses Dateinamens zum Herunterladen getestet: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ £ $ € {[]} + ´¨ ^ ~ '-_,;. txt
Auf IE7 funktioniert es für einige Zeichen, aber nicht für alle. Aber wen interessiert IE7 heutzutage?
Dies ist die Funktion, mit der ich sichere Dateinamen für Android generiere. Beachten Sie, dass ich nicht weiß, welche Zeichen unter Android unterstützt werden, aber dass ich getestet habe, dass diese sicher funktionieren:
@ TomZ: Ich habe in IE7 und IE8 getestet und es stellte sich heraus, dass ich nicht dem Apostroph (') entkommen musste. Haben Sie ein Beispiel, wo es fehlschlägt?
@ Dave Van den Eynde: Das Kombinieren der beiden Dateinamen in einer Zeile gemäß RFC6266 funktioniert mit Ausnahme von Android und IE7 + 8, und ich habe den Code aktualisiert, um dies widerzuspiegeln. Vielen Dank für den Vorschlag.
@Thilo: Keine Ahnung von GoodReader oder einem anderen Nicht-Browser. Mit dem Android-Ansatz haben Sie möglicherweise etwas Glück.
@ Alex Zhukovskiy: Ich weiß nicht warum, aber wie auf Connect besprochen , scheint es nicht besonders gut zu funktionieren.
quelle
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
und überspringen Sie das Schnüffeln des Browsers? Funktioniert das?Es gibt keine interoperable Möglichkeit, Nicht-ASCII-Namen in zu codieren
Content-Disposition
. Browserkompatibilität ist ein Chaos .Die theoretisch korrekte Syntax für die Verwendung von UTF-8 in
Content-Disposition
ist sehr seltsam:filename*=UTF-8''foo%c3%a4
(Ja, das ist ein Sternchen und keine Anführungszeichen außer einem leeren einfachen Anführungszeichen in der Mitte)Dieser Header ist ein bisschen nicht ganz Standard (die HTTP / 1.1-Spezifikation bestätigt seine Existenz , erfordert jedoch keine Unterstützung durch Clients).
Es gibt eine einfache und sehr robuste Alternative: Verwenden Sie eine URL, die den gewünschten Dateinamen enthält .
Wenn der Name nach dem letzten Schrägstrich der gewünschte ist, benötigen Sie keine zusätzlichen Überschriften!
Dieser Trick funktioniert:
Wenn Ihr Server das Umschreiben von URLs unterstützt (z. B.
mod_rewrite
in Apache), können Sie den Skriptteil vollständig ausblenden.Zeichen in URLs sollten in UTF-8 sein und bytenweise urlencodiert werden:
quelle
/:id/:filename
Methode ist sehr einfach und funktioniert, danke!Content-Disposition
und erstellen stattdessen sehr interessante Dateinamen (sie werden aus Ihrem Pfad generiert). Die einzige Lösung, um die eigene Gesundheit zu erhalten, besteht darinContent-Disposition: attachment
, den gewünschten Dateinamen als letzte PfadkomponenteRFC 6266 beschreibt die „ Verwendung des Content-Disposition-Header-Felds im Hypertext Transfer Protocol (HTTP) “. Zitat daraus:
Und in ihrem Beispielabschnitt :
In Anhang D finden Sie auch eine lange Liste von Vorschlägen zur Verbesserung der Interoperabilität. Es zeigt auch auf eine Site, die Implementierungen vergleicht . Aktuelle All-Pass-Tests, die für gängige Dateinamen geeignet sind, umfassen:
filename
Parameter " " verwendet.Dieser RFC 5987 verweist wiederum auf RFC 2231 , der das tatsächliche Format beschreibt. 2231 ist hauptsächlich für E-Mails bestimmt, und 5987 gibt an, welche Teile auch für HTTP-Header verwendet werden können. Verwechseln Sie dies nicht mit MIME-Headern, die in einem
multipart/form-data
HTTP- Body verwendet werden , der von RFC 2388 (insbesondere Abschnitt 4.4 ) und dem HTML 5-Entwurf geregelt wird .quelle
Das folgende Dokument, das mit dem von Jim in seiner Antwort erwähnten RFC-Entwurf verknüpft ist , befasst sich weiter mit der Frage und ist hier definitiv eine direkte Anmerkung wert:
Testfälle für HTTP Content-Disposition-Header und RFC 2231/2047-Codierung
quelle
in asp.net mvc2 benutze ich so etwas:
Ich denke, wenn Sie mvc (2) nicht verwenden, können Sie den Dateinamen einfach mit codieren
quelle
Setzen Sie den Dateinamen in doppelte Anführungszeichen. Das Problem wurde für mich gelöst. So was:
http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download
Ich habe mehrere Optionen getestet. Browser unterstützen die Spezifikationen nicht und verhalten sich anders. Ich glaube, doppelte Anführungszeichen sind die beste Option.
quelle
&
,%
,#
usw. So ist es , dass löst.Ich verwende die folgenden Codefragmente zum Codieren (vorausgesetzt, Dateiname enthält den Dateinamen und die Erweiterung der Datei, dh: test.txt):
PHP:
Java:
quelle
rawurlencode
zumindest für denfilename*=
Disposition-Header in PHP sein, davalue-chars
er inext-value
RFC 6266-> RFC 5987 verwendet wird (siehe tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) lässt keinen Speicherplatz zu, ohne dass ein Prozentsatz entweicht (filename=
andererseits scheint es, dass ein Speicherplatz ohne Entweichen überhaupt zulässig ist, obwohl hier nur ASCII vorhanden sein sollte). Es ist nicht notwendig, mit der vollen Strenge des Rawurlencodes zu codieren, so dass einige Zeichen nicht entkommen können: gist.github.com/brettz9/8752120In der ASP.NET-Web-API verschlüssele ich den Dateinamen mit einer URL:
quelle
Ich habe den folgenden Code in allen gängigen Browsern getestet, einschließlich älterer Explorer (über den Kompatibilitätsmodus), und er funktioniert überall gut:
quelle
Am Ende hatte ich den folgenden Code in meinem Skript "download.php" (basierend auf diesem Blogpost und diesen Testfällen ).
Dies verwendet die Standardmethode filename = "...", solange nur iso-latin1- und "safe" -Zeichen verwendet werden. Wenn nicht, wird der Dateiname * = UTF-8 '' url-codiert hinzugefügt. Gemäß diesem speziellen Testfall sollte es ab MSIE9 und auf neueren FF, Chrome, Safari funktionieren. In einer niedrigeren MSIE-Version sollte der Dateiname die ISO8859-1-Version des Dateinamens enthalten, wobei die Zeichen, die nicht in dieser Codierung enthalten sind, unterstrichen werden.
Schlussbemerkung: die max. Die Größe für jedes Header-Feld beträgt 8190 Byte für Apache. UTF-8 kann bis zu vier Bytes pro Zeichen umfassen. Nach rawurlencode ist es x3 = 12 Bytes pro Zeichen. Ziemlich ineffizient, aber es sollte theoretisch immer noch möglich sein, mehr als 600 "Lächeln"% F0% 9F% 98% 81 im Dateinamen zu haben.
quelle
Wenn Sie ein NodeJS-Backend verwenden, können Sie den folgenden Code verwenden, den ich hier gefunden habe
quelle
encodeURI(str)
. Als Beispiel mit Datumsangaben im Dateinamen:encodeURIComponent('"Kornél Kovács 1/1/2016')
=> "Kornél Kovács 1% 2F1% 2F2016" vs.encodeURI('"Kornél Kovács 1/1/2016')
=> "Kornél Kovács 01.01.2016"In PHP hat dies für mich getan (vorausgesetzt, der Dateiname ist UTF8-codiert):
Getestet gegen IE8-11, Firefox und Chrome.
Wenn der Browser interpretieren kann Dateinamen * = utf-8 , wird die UTF8-Version des Dateinamens verwendet, andernfalls wird der decodierte Dateiname verwendet. Wenn Ihr Dateiname Zeichen enthält, die in ISO-8859-1 nicht dargestellt werden können, sollten Sie
iconv
stattdessen die Verwendung in Betracht ziehen .quelle
Nur ein Update, da ich heute all diese Dinge als Antwort auf ein Kundenproblem ausprobiert habe
quelle
PHP-Framework Symfony 4 hat
$filenameFallback
inHeaderUtils::makeDisposition
. Sie können in dieser Funktion nach Details suchen - sie ähnelt den obigen Antworten.Anwendungsbeispiel:
quelle
Klassische ASP-Lösung
Die meisten modernen Browser unterstützen das Weitergeben
Filename
wieUTF-8
bisher, aber wie es bei einer von mir verwendeten Datei-Upload-Lösung der Fall war, die auf FreeASPUpload.Net basiert (Site existiert nicht mehr, Link verweist auf archive.org ) , würde es nicht als Parsing des funktionieren Binär basiert auf dem Lesen von Einzelbyte-ASCII-codierten Zeichenfolgen, was gut funktioniert hat, wenn Sie UTF-8-codierte Daten übergeben haben, bis Sie zu Zeichen gelangen, die ASCII nicht unterstützt.Ich konnte jedoch eine Lösung finden, um den Code zum Lesen und Parsen der Binärdatei als UTF-8 zu erhalten.
Das Guthaben geht an Pure ASP File Upload, indem die
BytesToString()
Funktioninclude_aspuploader.asp
in meinem eigenen Code implementiert wird, mit dem ichUTF-8
Dateinamen zum Laufen bringen konnte.Nützliche Links
Multipart / Formulardaten und UTF-8 in einer ASP Classic-Anwendung
Unterschiede im Unicode-, UTF-, ASCII- und ANSI-Format
quelle
Wir hatten ein ähnliches Problem in einer Webanwendung und lasen schließlich den Dateinamen aus dem HTML-
<input type="file">
Code und stellten ihn in der URL-codierten Form in einem neuen HTML-Code ein<input type="hidden">
. Natürlich mussten wir den Pfad wie "C: \ fakepath \" entfernen, der von einigen Browsern zurückgegeben wird.Dies beantwortet natürlich nicht direkt die Frage des OP, kann aber eine Lösung für andere sein.
quelle
Normalerweise verschlüssele ich die Dateinamen per URL (mit% xx) und es scheint in allen Browsern zu funktionieren. Vielleicht möchten Sie trotzdem einige Tests durchführen.
quelle