624 Stimmen

Wie kodiert man den Parameter filename des Content-Disposition-Headers in HTTP?

Webanwendungen, die eine Ressource erzwingen wollen, die heruntergeladen und nicht direkt gerendert in einem Webbrowser eine Content-Disposition Kopfzeile in der HTTP-Antwort des Formulars:

Content-Disposition: attachment; filename=_FILENAME_

El filename kann verwendet werden, um einen Namen für die Datei vorzuschlagen, in die die Ressource vom Browser heruntergeladen wird. RFC 2183 (Content-Disposition) heißt es jedoch in Abschnitt 2.3 (The Filename Parameter), dass der Dateiname nur US-ASCII-Zeichen enthalten darf:

Die aktuelle [RFC 2045]-Grammatik schränkt ein Parameterwerte (und damit Content-Disposition Dateinamen) auf US-ASCII. Wir erkennen die große Wünschenswertheit, beliebige Zeichensätze in Zeichensätze in Dateinamen zuzulassen, aber es ist den Rahmen dieses Dokuments, die notwendigen die notwendigen Mechanismen zu definieren.

Es gibt jedoch empirische Belege dafür, dass die meisten gängigen Webbrowser heute zwar Nicht-US-ASCII-Zeichen zulassen, sich aber (in Ermangelung einer Norm) nicht über das Kodierungsschema und die Zeichensatzspezifikation des Dateinamens einig sind. Die Frage ist also, welche verschiedenen Schemata und Kodierungen von den gängigen Browsern verwendet werden, wenn der Dateiname "naïvefile" (ohne Anführungszeichen und mit dem dritten Buchstaben U+00EF) im Content-Disposition-Header kodiert werden muss.

Für die Zwecke dieser Frage, gängige Browser sein:

  • Google Chrome
  • Safari
  • Internet Explorer oder Edge
  • Firefox
  • Oper

0 Stimmen

Es funktioniert für Mobile Safari (raw utf-8 wie von @Martin Ørding-Thomsen vorgeschlagen), aber das funktioniert nicht für GoodReader vom gleichen Gerät. Irgendwelche Ideen?

0 Stimmen

1 Stimmen

Kornel's Antwort hat sich als der Weg des geringsten Widerstands erwiesen, wenn man das letzte Segment des Weges festlegen kann; gekoppelt ist dies mit Content-Disposition: attachment .

429voto

Ich weiß, dies ist ein alter Beitrag, aber er ist immer noch sehr aktuell. Ich habe festgestellt, dass moderne Browser rfc5987 unterstützen, was eine utf-8-Kodierung erlaubt, und zwar prozentual kodiert (url-encoded). Dann Naïve file.txt wird:

Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt

Safari (5) unterstützt dies nicht. Stattdessen sollten Sie den Safari-Standard verwenden und den Dateinamen direkt in Ihren utf-8-kodierten Header schreiben:

Content-Disposition: attachment; filename=Naïve file.txt

IE8 und ältere Versionen unterstützen dies ebenfalls nicht, und Sie müssen den IE-Standard der utf-8-Kodierung verwenden, d. h. prozentual kodiert:

Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt

In ASP.Net verwende ich den folgenden Code:

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.Browser.Browser == "Safari")
    contentDisposition = "attachment; filename=" + fileName;
else
    contentDisposition = "attachment; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

Ich habe das oben genannte mit IE7, IE8, IE9, Chrome 13, Opera 11, FF5 und Safari 5 getestet.

Update November 2013:

Hier ist der Code, den ich derzeit verwende. Ich muss immer noch den IE8 unterstützen, also kann ich den ersten Teil nicht loswerden. Es hat sich herausgestellt, dass Browser auf Android den eingebauten Android-Download-Manager verwenden und dieser kann Dateinamen nicht zuverlässig auf die übliche Art und Weise parsen.

string contentDisposition;
if (Request.Browser.Browser == "IE" && (Request.Browser.Version == "7.0" || Request.Browser.Version == "8.0"))
    contentDisposition = "attachment; filename=" + Uri.EscapeDataString(fileName);
else if (Request.UserAgent != null && Request.UserAgent.ToLowerInvariant().Contains("android")) // android built-in download manager (all browsers on android)
    contentDisposition = "attachment; filename=\"" + MakeAndroidSafeFileName(fileName) + "\"";
else
    contentDisposition = "attachment; filename=\"" + fileName + "\"; filename*=UTF-8''" + Uri.EscapeDataString(fileName);
Response.AddHeader("Content-Disposition", contentDisposition);

Das oben genannte wurde jetzt in IE7-11, Chrome 32, Opera 12, FF25, Safari 6 getestet, wobei dieser Dateiname zum Download verwendet wurde: abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§!#¤%&()=`@£$€{[]}+'¨^~'-_,;.txt

Im IE7 funktioniert es bei einigen Zeichen, aber nicht bei allen. Aber wer kümmert sich heutzutage noch um den IE7?

Dies ist die Funktion, die ich verwende, um sichere Dateinamen für Android zu generieren. Beachten Sie, dass ich nicht weiß, welche Zeichen auf Android unterstützt werden, aber dass ich getestet habe, dass diese sicher funktionieren:

private static readonly Dictionary<char, char> AndroidAllowedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ._-+,@£$€!½§~'=()[]{}0123456789".ToDictionary(c => c);
private string MakeAndroidSafeFileName(string fileName)
{
    char[] newFileName = fileName.ToCharArray();
    for (int i = 0; i < newFileName.Length; i++)
    {
        if (!AndroidAllowedChars.ContainsKey(newFileName[i]))
            newFileName[i] = '_';
    }
    return new string(newFileName);
}

@TomZ: Ich habe es im IE7 und IE8 getestet, und es stellte sich heraus, dass ich das Hochkomma (') nicht ausblenden musste. Haben Sie ein Beispiel, bei dem es nicht funktioniert?

@Dave Van den Eynde: Die Kombination der beiden Dateinamen in einer Zeile gemäß RFC6266 funktioniert, außer bei Android und IE7+8, und ich habe den Code aktualisiert, um dies zu berücksichtigen. Vielen Dank für die Anregung.

@Thilo: Keine Ahnung von GoodReader oder anderen Nicht-Browsern. Vielleicht haben Sie Glück, wenn Sie den Android-Ansatz verwenden.

@Alex Zhukovskiy: Ich weiß nicht, warum, aber wie auf Verbinden Sie es scheint nicht besonders gut zu funktionieren.

187voto

Kornel Punkte 94135

Es gibt eine einfache und sehr robuste Alternative: eine URL verwenden, die den gewünschten Dateinamen enthält .

Wenn der Name nach dem letzten Schrägstrich der gewünschte ist, brauchen Sie keine zusätzlichen Kopfzeilen!

Dieser Trick funktioniert:

/real_script.php/fake_filename.doc

Und wenn Ihr Server URL-Rewriting unterstützt (z. B. mod_rewrite im Apache), dann können Sie den Skriptteil vollständig ausblenden.

Zeichen in URLs sollten in UTF-8, urlencoded Byte für Byte sein:

/mot%C3%B6rhead   # motörhead

103voto

Jim Punkte 70896

Eine Diskussion darüber, einschließlich Links zu Browser-Tests und Abwärtskompatibilität, findet sich in der vorgeschlagenen RFC 5987 "Zeichensatz und Sprachkodierung für Hypertext Transfer Protocol (HTTP) Header Field Parameters".

RFC 2183 zeigt an, dass solche Kopfzeilen gemäß der RFC 2184 , das ersetzt wurde durch RFC 2231 die durch den obigen RFC-Entwurf abgedeckt sind.

90voto

MvG Punkte 54213

RFC 6266 beschreibt die " Verwendung des Header-Feldes "Content-Disposition" im Hypertext Transfer Protocol (HTTP) ". Ich zitiere daraus:

6. Überlegungen zur Internationalisierung

Die " filename* "-Parameter ( Abschnitt 4.3 ), unter Verwendung der definierten Kodierung in [ RFC5987 ], erlaubt dem Server die Übertragung von Zeichen außerhalb des ISO-8859-1-Zeichensatzes zu übermitteln und optional auch die verwendete Sprache anzugeben.

Und in ihrem Beispiele :

Dieses Beispiel ist dasselbe wie das obige, allerdings wird der Parameter "filename" hinzugefügt hinzu, um die Kompatibilität mit User Agents zu gewährleisten, die die RFC 5987 :

Content-Disposition: attachment;
                     filename="EURO rates";
                     filename*=utf-8''%e2%82%ac%20rates

Hinweis: Diejenigen User-Agents, die nicht die RFC 5987 Kodierung ignorieren " filename* ", wenn es nach " filename ".

Unter Anhang D Es gibt auch eine lange Liste von Vorschlägen zur Verbesserung der Interoperabilität. Er verweist auch auf eine Website, die Implementierungen vergleicht . Zu den aktuellen All-Pass-Tests, die für gängige Dateinamen geeignet sind, gehören:

  • attwithisofnplain : einfacher ISO-8859-1 Dateiname mit doppelten Anführungszeichen und ohne Kodierung. Dies erfordert einen Dateinamen, der ausschließlich aus ISO-8859-1 besteht und keine Prozentzeichen enthält, zumindest nicht vor den Hex-Ziffern.
  • beide : zwei Parameter in der oben beschriebenen Reihenfolge. Sollte für die meisten Dateinamen in den meisten Browsern funktionieren, obwohl der IE8 das " filename Parameter".

Das RFC 5987 verweist seinerseits auf RFC 2231 , die das eigentliche Format beschreibt. 2231 ist in erster Linie für E-Mails gedacht, und 5987 legt fest, welche Teile auch für HTTP-Header verwendet werden können. Verwechseln Sie dies nicht mit MIME-Headern, die innerhalb einer multipart/form-data HTTP Körper die sich nach RFC 2388 ( Abschnitt 4.4 im Besonderen) und die HTML 5 Entwurf .

15voto

Atif Aziz Punkte 35092

Das folgende Dokument, das von den RFC-Entwurf erwähnt von Jim geht in seiner Antwort weiter auf die Frage ein und ist hier sicherlich einen direkten Hinweis wert:

Testfälle für HTTP Content-Disposition-Header und RFC 2231/2047-Kodierung

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X