Wie codiere ich den Dateinamenparameter des Content-Disposition-Headers in HTTP?


535

Web - Anwendungen , die eine Ressource erzwingen wollen werden heruntergeladen , anstatt direkt gerendert in einem Web - Browser eine Ausgabe - Content-DispositionHeader in der HTTP - Antwort in der Form:

Content-Disposition: attachment; filename=FILENAME

Mit dem filenameParameter 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

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


1
Kornels Antwort erwies sich als der Weg des geringsten Widerstands, wenn Sie das letzte Segment des Weges festlegen können. kopple das mit Content-Disposition: attachment.
Antti Haapala

Antworten:


94

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 .


5
Beachten Sie auch, dass der Internet-Entwurf (nicht "RFC-Entwurf") fertiggestellt wurde und das endgültige Dokument RFC 5987 ( greenbytes.de/tech/webdav/rfc5987.html ) ist
Julian Reschke

11
Im Zusammenhang damit habe ich festgestellt, dass Firefox (Versionen 4-9 einschließlich) unterbrochen wird, wenn der Dateiname ein Komma (,) enthält, z Content-Disposition: filename="foo, bar.pdf". Das Ergebnis ist, dass Firefox die Datei korrekt herunterlädt, aber die .partErweiterung beibehält (z foo,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.
catchdave


5
@catchdave: Du hast den "Anhang" vergessen; Teil.
Christoffer Hammarström

6
Alles in allem ist dies nichts anderes als eine Nur-Link-Antwort mit 74 Upvotes.
Antti Haapala

364

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:

Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.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:

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

IE8 und älter unterstützen es ebenfalls nicht und Sie müssen den IE-Standard der utf-8-Codierung verwenden, prozentual codiert:

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, 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.

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);

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:

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 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.


1
Es funktioniert für Mobile Safari (raw utf-8 wie oben vorgeschlagen), aber das funktioniert nicht für GoodReader vom selben Gerät. Irgendwelche Ideen?
Thilo

1
IE7 und 8 müssen auch Apostrophe entkommen: .Replace ("'", Uri.HexEscape (' \ ''))
TomZ

1
Das direkte Schreiben von UTF-8-Zeichen scheint für aktuelle Versionen von Firefox, Chrome und Opera zu funktionieren. Safari & IE wurde nicht getestet.
Martin Tournoij

20
Warum kombinieren Sie sie nicht als Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txtund überspringen Sie das Schnüffeln des Browsers? Funktioniert das?
Dave Van den Eynde

9
Die freundlichen Leute bei fastmail haben eine andere Problemumgehung gefunden: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: Anhang; Dateiname = "foo-% c3% a4.html"; Dateiname * = UTF-8''foo-% c3% a4.html Wenn Sie den Dateinamen zweimal (einmal ohne UTF-8-Präfix und einmal mit) angeben, funktioniert er in IE8-11, Edge, Chrome, Firefox und Safari ( scheint wie eine Apple Fixed Safari, also funktioniert es jetzt auch dort)
Wullinkm

169

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:

/real_script.php/fake_filename.doc

Wenn Ihr Server das Umschreiben von URLs unterstützt (z. B. mod_rewritein Apache), können Sie den Skriptteil vollständig ausblenden.

Zeichen in URLs sollten in UTF-8 sein und bytenweise urlencodiert werden:

/mot%C3%B6rhead   # motörhead

3
Versuchen Sie GetAttachment.aspx / fake_filename.doc? Id = 34 (obwohl es möglicherweise nur Apache-Eigenart ist)
Kornel

2
das ist eine fantastische Lösung; hat mir sehr geholfen. Vielen Dank.
kristopolous

6
Ich ging den Kaninchenpfad entlang und versuchte einige der anderen Lösungen; Der Versuch, den richtigen Browser und die richtige Version zu finden, um die Header richtig einzustellen, ist ein zu großer Albtraum. Chrome hat sich fälschlicherweise als Safari identifiziert, das sich überhaupt nicht gleich verhält (Komma-Unterbrechungen, wenn nicht richtig codiert). Sparen Sie sich die Mühe, verwenden Sie diese Lösung und aliasen Sie die URL nach Bedarf.
Mpen

3
Die /:id/:filenameMethode ist sehr einfach und funktioniert, danke!
Luca Steeb

2
Tausendmal "Ja". Sie werden damit ernsthaft Zeit gewinnen. Gleichmäßiger - einige Android-Browser ignorieren das Content-Dispositionund erstellen stattdessen sehr interessante Dateinamen (sie werden aus Ihrem Pfad generiert). Die einzige Lösung, um die eigene Gesundheit zu erhalten, besteht darin Content-Disposition: attachment, den gewünschten Dateinamen als letzte Pfadkomponente
festzulegen

73

RFC 6266 beschreibt die „ Verwendung des Content-Disposition-Header-Felds im Hypertext Transfer Protocol (HTTP) “. Zitat daraus:

6. Überlegungen zur Internationalisierung

Mit dem filename*Parameter “ ” ( Abschnitt 4.3 ) kann der Server unter Verwendung der in [ RFC5987 ] definierten Codierung Zeichen außerhalb des Zeichensatzes ISO-8859-1 übertragen und optional die verwendete Sprache angeben.

Und in ihrem Beispielabschnitt :

Dieses Beispiel ist das gleiche wie das obige, fügt jedoch den Parameter "Dateiname" hinzu, um die Kompatibilität mit Benutzeragenten zu gewährleisten, die RFC 5987 nicht implementieren :

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

Hinweis: Benutzeragenten, die die RFC 5987- Codierung nicht unterstützen , ignorieren " filename*", wenn sie nach " filename" auftritt .

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:

  • attwithisofnplain : einfacher ISO-8859-1-Dateiname mit doppelten Anführungszeichen und ohne Codierung. Dies erfordert einen Dateinamen, der ausschließlich ISO-8859-1 lautet und keine Prozentzeichen enthält, zumindest nicht vor hexadezimalen Ziffern.
  • attfnboth : zwei Parameter in der oben beschriebenen Reihenfolge. Sollte für die meisten Dateinamen in den meisten Browsern funktionieren, obwohl IE8 den filenameParameter " " 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-dataHTTP- Body verwendet werden , der von RFC 2388 (insbesondere Abschnitt 4.4 ) und dem HTML 5-Entwurf geregelt wird .


1
Ich hatte Probleme in Safari. Beim Herunterladen von Dateien mit russischen Namen wurden fehlerhafte und unlesbare Zeichen empfangen. Die Lösung hat geholfen. Aber wir müssen einen Header in einer einzigen Zeile senden (!!!).
evtuhovdo

16

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


Beachten Sie, dass Sie beide Arten der Codierung des Dateinamenparameters angeben können und dass sie mit alten und neuen Browsern (in diesem Fall MSIE8 und Safari) korrekt zu funktionieren scheinen. Überprüfen Sie attfnboth in dem von @AtifAziz erwähnten Bericht.
Pablo Montilla

11

in asp.net mvc2 benutze ich so etwas:

return File(
    tempFile
    , "application/octet-stream"
    , HttpUtility.UrlPathEncode(fileName)
    );

Ich denke, wenn Sie mvc (2) nicht verwenden, können Sie den Dateinamen einfach mit codieren

HttpUtility.UrlPathEncode(fileName)

2
Die URL-Codierung für die Dateinamencodierung ist ungültig. Browser sollten diese nicht per URL dekodieren.
SerialSeb

IE 11 dekodiert definitiv keine URL-Codierung in diesem Feld.
Pseudocoder

Aber es musste UrlEncoded sein, wenn der Browser Chrome oder IE ist, andere wie FF, Safari und Opera funktionieren gut ohne Codierung
Reza

11

Setzen Sie den Dateinamen in doppelte Anführungszeichen. Das Problem wurde für mich gelöst. So was:

Content-Disposition: attachment; filename="My Report.doc"

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.


3
Dies löst leider nicht alle in den obigen Antworten erläuterten Probleme.
Luca Steeb

2
Auf diese Weise können Sie einen Dateinamen mit Leerzeichen zurückzukehren &, %, #usw. So ist es , dass löst.
Don Cheadle

Was passiert, wenn der Dateiname doppelte Anführungszeichen enthält (ja, dies kann passieren)? Wie in RFC 6266 angegeben, ist der Dateiname eine "Anführungszeichenfolge", und wie in RFC 2616 angegeben, sollten doppelte Anführungszeichen in einer Anführungszeichenfolge mit einem Backslash maskiert werden.
Christophe Roussy

10

Ich verwende die folgenden Codefragmente zum Codieren (vorausgesetzt, Dateiname enthält den Dateinamen und die Erweiterung der Datei, dh: test.txt):


PHP:

if ( strpos ( $_SERVER [ 'HTTP_USER_AGENT' ], "MSIE" ) > 0 )
{
     header ( 'Content-Disposition: attachment; filename="' . rawurlencode ( $fileName ) . '"' );
}
else
{
     header( 'Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ( $fileName ) );
}

Java:

fileName = request.getHeader ( "user-agent" ).contains ( "MSIE" ) ? URLEncoder.encode ( fileName, "utf-8") : MimeUtility.encodeWord ( fileName );
response.setHeader ( "Content-disposition", "attachment; filename=\"" + fileName + "\"");

Richtig, es sollte rawurlencodezumindest für den filename*=Disposition-Header in PHP sein, da value-charser in ext-valueRFC 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/8752120
Brett Zamir

9

In der ASP.NET-Web-API verschlüssele ich den Dateinamen mit einer URL:

public static class HttpRequestMessageExtensions
{
    public static HttpResponseMessage CreateFileResponse(this HttpRequestMessage request, byte[] data, string filename, string mediaType)
    {
        HttpResponseMessage response = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new MemoryStream(data);
        stream.Position = 0;

        response.Content = new StreamContent(stream);

        response.Content.Headers.ContentType = 
            new MediaTypeHeaderValue(mediaType);

        // URL-Encode filename
        // Fixes behavior in IE, that filenames with non US-ASCII characters
        // stay correct (not "_utf-8_.......=_=").
        var encodedFilename = HttpUtility.UrlEncode(filename, Encoding.UTF8);

        response.Content.Headers.ContentDisposition =
            new ContentDispositionHeaderValue("attachment") { FileName = encodedFilename };
        return response;
    }
}

IE 9 Nicht behoben
IE 9 behoben


5

Ich habe den folgenden Code in allen gängigen Browsern getestet, einschließlich älterer Explorer (über den Kompatibilitätsmodus), und er funktioniert überall gut:

$filename = $_GET['file']; //this string from $_GET is already decoded
if (strstr($_SERVER['HTTP_USER_AGENT'],"MSIE"))
  $filename = rawurlencode($filename);
header('Content-Disposition: attachment; filename="'.$filename.'"');

5

Am Ende hatte ich den folgenden Code in meinem Skript "download.php" (basierend auf diesem Blogpost und diesen Testfällen ).

$il1_filename = utf8_decode($filename);
$to_underscore = "\"\\#*;:|<>/?";
$safe_filename = strtr($il1_filename, $to_underscore, str_repeat("_", strlen($to_underscore)));

header("Content-Disposition: attachment; filename=\"$safe_filename\""
.( $safe_filename === $filename ? "" : "; filename*=UTF-8''".rawurlencode($filename) ));

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.


... aber die maximale übertragbare Dateinamenlänge hängt auch vom Client ab. Ich habe gerade herausgefunden, dass höchstens [89 smiles😁] .pdf-Dateiname über MSIE11 gelangt. In Firefox37 ist es höchstens [111x 😁] .pdf. Chrome41 schneidet den Dateinamen beim 110. Lächeln ab. Interessanterweise wird das Suffix in Ordnung übertragen.
Apurkrt

5

Wenn Sie ein NodeJS-Backend verwenden, können Sie den folgenden Code verwenden, den ich hier gefunden habe

var fileName = 'my file(2).txt';
var header = "Content-Disposition: attachment; filename*=UTF-8''" 
             + encodeRFC5987ValueChars(fileName);

function encodeRFC5987ValueChars (str) {
    return encodeURIComponent(str).
        // Note that although RFC3986 reserves "!", RFC5987 does not,
        // so we do not need to escape it
        replace(/['()]/g, escape). // i.e., %27 %28 %29
        replace(/\*/g, '%2A').
            // The following are not required for percent-encoding per RFC5987, 
            // so we can allow for a little better readability over the wire: |`^
            replace(/%(?:7C|60|5E)/g, unescape);
}

1
Besser zu benutzen 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"
gdibble

4

In PHP hat dies für mich getan (vorausgesetzt, der Dateiname ist UTF8-codiert):

header('Content-Disposition: attachment;'
    . 'filename="' . addslashes(utf8_decode($filename)) . '";'
    . 'filename*=utf-8\'\'' . rawurlencode($filename));

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 iconvstattdessen die Verwendung in Betracht ziehen .


3
Obwohl dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, warum und / oder wie er die Frage beantwortet, ihren langfristigen Wert erheblich verbessern. Bitte bearbeiten Sie Ihre Antwort, um eine Erklärung hinzuzufügen.
Toby Speight

2
Whoa, keine der oben genannten Nur-Code-Antworten wurde so herabgestuft oder kritisiert. Außerdem fand ich das Warum bereits gut genug beantwortet: IE interpretiert den Dateinamen * = utf-8 nicht, benötigt aber die ISO8859-1-Version des Dateinamens, die dieses Skript bietet. Ich wollte den Faulen nur einen funktionierenden einfachen Code für PHP geben.
Gustav

Ich denke, dies wurde abgelehnt, weil die Frage nicht sprachspezifisch ist, sondern darüber, an welche RFCs bei der Implementierung der Header-Codierung zu halten ist. Vielen Dank jedoch für diese Antwort, für PHP, dieser Code ließ meine Leiden verschwinden.
J4K3

Vielen Dank. Diese Antwort hat die Frage möglicherweise nicht genau beantwortet, aber sie war genau das, wonach ich gesucht habe, und hat mir geholfen, das Problem in Python zu lösen.
Lyndsy Simon

1
Ich bin mir ziemlich sicher, dass dieser Code als Angriffsvektor verwendet werden kann, wenn der Benutzer den Namen der Datei steuern kann.
Antti Haapala

3

Nur ein Update, da ich heute all diese Dinge als Antwort auf ein Kundenproblem ausprobiert habe

  • Mit Ausnahme von Safari, das für Japanisch konfiguriert ist, funktionierten alle von unserem Kunden getesteten Browser am besten mit Dateiname = text.pdf - wobei Text ein Kundenwert ist, der von ASP.Net/IIS in utf-8 ohne URL-Codierung serialisiert wurde. Aus irgendeinem Grund würde Safari, das für Englisch konfiguriert ist, eine Datei mit dem japanischen Namen utf-8 akzeptieren und ordnungsgemäß speichern, aber der gleiche Browser, der für Japanisch konfiguriert ist, würde die Datei mit den nicht interpretierten Zeichen utf-8 speichern. Alle anderen getesteten Browser schienen am besten zu funktionieren (unabhängig von der Sprachkonfiguration), wobei der Dateiname utf-8 ohne URL-Codierung codiert war.
  • Ich konnte keinen einzigen Browser - Implementierung Rfc5987 / 8187 finden überhaupt . Ich habe mit den neuesten Chrome-, Firefox-Builds sowie IE 11 und Edge getestet. Ich habe versucht, den Header nur mit dem Dateinamen * = utf-8''texturlencoded.pdf zu setzen und ihn mit beiden Dateinamen = text.pdf zu setzen. Dateiname * = utf-8''texturlencoded.pdf. Keine der Funktionen von Rfc5987 / 8187 schien in einer der oben genannten Funktionen korrekt verarbeitet zu werden.

Dies ist ein gutes Update. Können Sie die spezifischen Tests, die Sie versucht haben, näher erläutern?
Brad

3

PHP-Framework Symfony 4 hat $filenameFallbackin HeaderUtils::makeDisposition. Sie können in dieser Funktion nach Details suchen - sie ähnelt den obigen Antworten.

Anwendungsbeispiel:

$filenameFallback = preg_replace('#^.*\.#', md5($filename) . '.', $filename);
$disposition = $response->headers->makeDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $filename, $filenameFallback);
$response->headers->set('Content-Disposition', $disposition);

1

Klassische ASP-Lösung

Die meisten modernen Browser unterstützen das Weitergeben Filenamewie UTF-8bisher, 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.

Public Function BytesToString(bytes)    'UTF-8..
  Dim bslen
  Dim i, k , N 
  Dim b , count 
  Dim str

  bslen = LenB(bytes)
  str=""

  i = 0
  Do While i < bslen
    b = AscB(MidB(bytes,i+1,1))

    If (b And &HFC) = &HFC Then
      count = 6
      N = b And &H1
    ElseIf (b And &HF8) = &HF8 Then
      count = 5
      N = b And &H3
    ElseIf (b And &HF0) = &HF0 Then
      count = 4
      N = b And &H7
    ElseIf (b And &HE0) = &HE0 Then
      count = 3
      N = b And &HF
    ElseIf (b And &HC0) = &HC0 Then
      count = 2
      N = b And &H1F
    Else
      count = 1
      str = str & Chr(b)
    End If

    If i + count - 1 > bslen Then
      str = str&"?"
      Exit Do
    End If

    If count>1 then
      For k = 1 To count - 1
        b = AscB(MidB(bytes,i+k+1,1))
        N = N * &H40 + (b And &H3F)
      Next
      str = str & ChrW(N)
    End If
    i = i + count
  Loop

  BytesToString = str
End Function

Das Guthaben geht an Pure ASP File Upload, indem die BytesToString()Funktion include_aspuploader.aspin meinem eigenen Code implementiert wird, mit dem ich UTF-8Dateinamen zum Laufen bringen konnte.


Nützliche Links


-1

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.


1
Ganz anderes Problem. Bei der Frage geht es um das Herunterladen , bei Ihrer Antwort geht es um das Hochladen .
Oskar Berggren

-3

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.


10
Ich habe in ein paar getestet und es funktioniert nicht in allen Browsern so, daher die Frage. :)
Atif Aziz
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.