Comment encoder le paramètre de nom de fichier de l'en-tête Content-Disposition en HTTP?

535

Les applications Web qui souhaitent forcer le téléchargement d' une ressource plutôt que son rendu direct dans un navigateur Web génèrent un en- Content-Dispositiontête dans la réponse HTTP du formulaire:

Content-Disposition: attachment; filename=FILENAME

Le filenameparamètre peut être utilisé pour suggérer un nom pour le fichier dans lequel la ressource est téléchargée par le navigateur. La RFC 2183 (Content-Disposition), cependant, indique dans la section 2.3 (The Filename Parameter) que le nom de fichier ne peut utiliser que des caractères US-ASCII:

La grammaire actuelle [RFC 2045] limite les valeurs des paramètres (et donc les noms de fichiers Content-Disposition) à US-ASCII. Nous reconnaissons la grande opportunité de permettre des jeux de caractères arbitraires dans les noms de fichiers, mais il est hors de la portée de ce document de définir les mécanismes nécessaires.

Il existe des preuves empiriques, néanmoins, que la plupart des navigateurs Web actuels semblent autoriser les caractères non US-ASCII mais (faute de norme) ne sont pas d'accord sur le schéma de codage et la spécification du jeu de caractères du nom de fichier. La question est alors de savoir quels sont les différents schémas et encodages utilisés par les navigateurs populaires si le nom de fichier «naïvefile» (sans guillemets et où la troisième lettre est U + 00EF) devait être encodé dans l'en-tête Content-Disposition?

Aux fins de cette question, les navigateurs populaires étant:

  • Firefox
  • Internet Explorer
  • Safari
  • Google Chrome
  • Opéra
Atif Aziz
la source
Je l'ai fait fonctionner pour Mobile Safari (utf-8 brut comme suggéré par @Martin Ørding-Thomsen), mais cela ne fonctionne pas pour GoodReader à partir du même appareil. Des idées?
Thilo
Voir aussi cette question similaire
juergen d
1
La réponse de Kornel s'est avérée être le chemin de moindre résistance, si vous pouvez définir le dernier segment du chemin; coupler avec Content-Disposition: attachment.
Antti Haapala

Réponses:

94

Il y a une discussion à ce sujet, y compris des liens vers les tests du navigateur et la compatibilité descendante, dans la RFC 5987 proposée , "Jeu de caractères et codage de langue pour les paramètres de champ d'en-tête HTTP (Hypertext Transfer Protocol)".

La RFC 2183 indique que ces en-têtes doivent être codés conformément à la RFC 2184 , qui était obsolète par la RFC 2231 , couverte par le projet de RFC ci-dessus.

Jim
la source
5
Notez également que le brouillon Internet (pas le "brouillon RFC") est terminé et que le document final est le RFC 5987 ( greenbytes.de/tech/webdav/rfc5987.html )
Julian Reschke
11
À ce sujet, j'ai découvert que Firefox (versions 4-9 inclusivement) se casse s'il y a une virgule (,) dans le nom de fichier, par exemple Content-Disposition: filename="foo, bar.pdf". Le résultat est que Firefox télécharge correctement le fichier mais conserve l' .partextension (par exemple foo,bar.pdf-1.part). Ensuite, bien sûr, le fichier ne s'ouvrira pas correctement car l'application n'est pas associée à .part. D'autres caractères ASCII semblent fonctionner correctement.
catchdave
3
Pour plus d'informations sur le comportement d'IE, voir blogs.msdn.com/b/ieinternals/archive/2010/06/07/…
EricLaw
5
@catchdave: Vous avez oublié la "pièce jointe;" partie.
Christoffer Hammarström
6
Dans l'ensemble, ce n'est rien d'autre qu'une réponse de lien uniquement avec 74 votes positifs.
Antti Haapala
364

Je sais que c'est un ancien poste mais il est toujours très pertinent. J'ai constaté que les navigateurs modernes prennent en charge rfc5987, qui permet le codage utf-8, codé en pourcentage (codé en url). Alors Naïve file.txt devient:

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

Safari (5) ne prend pas en charge cela. Au lieu de cela, vous devez utiliser la norme Safari d'écrire le nom de fichier directement dans votre en-tête encodé utf-8:

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

IE8 et les versions antérieures ne le prennent pas en charge non plus et vous devez utiliser la norme IE d'encodage utf-8, pourcentage encodé:

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

Dans ASP.Net, j'utilise le code suivant:

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

J'ai testé ce qui précède en utilisant IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.

Mise à jour de novembre 2013:

Voici le code que j'utilise actuellement. Je dois encore supporter IE8, donc je ne peux pas me débarrasser de la première partie. Il s'avère que les navigateurs sur Android utilisent le gestionnaire de téléchargement Android intégré et qu'il ne peut pas analyser de manière fiable les noms de fichiers de la manière standard.

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

Ce qui précède maintenant testé dans IE7-11, Chrome 32, Opera 12, FF25, Safari 6, en utilisant ce nom de fichier pour le téléchargement: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ £ $ € {[]} + ´¨ ^ ~ '-_,;. txt

Sur IE7, cela fonctionne pour certains personnages mais pas pour tous. Mais qui se soucie d'IE7 de nos jours?

C'est la fonction que j'utilise pour générer des noms de fichiers sûrs pour Android. Notez que je ne sais pas quels caractères sont pris en charge sur Android mais que j'ai testé que ceux-ci fonctionnent à coup sûr:

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: J'ai testé dans IE7 et IE8 et il s'est avéré que je n'avais pas besoin d'échapper à l'apostrophe ('). Avez-vous un exemple où cela échoue?

@Dave Van den Eynde: La combinaison des deux noms de fichiers sur une seule ligne selon RFC6266 fonctionne sauf pour Android et IE7 + 8 et j'ai mis à jour le code pour refléter cela. Merci pour la suggestion.

@Thilo: Aucune idée de GoodReader ou de tout autre non-navigateur. Vous pourriez avoir de la chance en utilisant l'approche Android.

@Alex Zhukovskiy: Je ne sais pas pourquoi mais comme discuté sur Connect, cela ne semble pas très bien fonctionner.

Martin Ørding-Thomsen
la source
1
Je l'ai fait fonctionner pour Mobile Safari (utf-8 brut comme suggéré ci-dessus), mais cela ne fonctionne pas pour GoodReader à partir du même appareil. Des idées?
Thilo
1
IE7 et 8 nécessitent également des apostrophes échappés: .Replace ("'", Uri.HexEscape (' \ ''))
TomZ
1
L'écriture directe de caractères UTF-8 semble fonctionner pour les versions actuelles de Firefox, Chrome et Opera. N'a pas testé Safari et IE.
Martin Tournoij
21
Pourquoi ne pas les combiner Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txtet ignorer le reniflement du navigateur? Cela fonctionnerait-il?
Dave Van den Eynde
9
Les gens aimables de fastmail ont trouvé une autre solution: blog.fastmail.com/2011/06/24/download-non-english-filenames Content-Disposition: attachment; filename = "foo-% c3% a4.html"; filename * = UTF-8''foo-% c3% a4.html La spécification de fileName deux fois (une fois sans le préfixe UTF-8 et une fois avec) le fait fonctionner dans IE8-11, Edge, Chrome, Firefox et Safari ( semble être un safari fixe pour Apple, donc ça marche aussi maintenant)
wullinkm
169

Il existe une alternative simple et très robuste: utilisez une URL contenant le nom de fichier souhaité .

Lorsque le nom après la dernière barre oblique est celui que vous voulez, vous n'avez pas besoin d'en-têtes supplémentaires!

Cette astuce fonctionne:

/real_script.php/fake_filename.doc

Et si votre serveur prend en charge la réécriture d'URL (par exemple mod_rewritedans Apache), vous pouvez entièrement masquer la partie de script.

Les caractères des URL doivent être en UTF-8, codés en octets par octets:

/mot%C3%B6rhead   # motörhead
Kornel
la source
3
Essayez GetAttachment.aspx / fake_filename.doc? Id = 34 (bien qu'il puisse s'agir d'une excentricité Apache uniquement)
Kornel
2
c'est une solution fantastique; m'a vraiment beaucoup aidé. Merci.
kristopole le
6
Je suis descendu la piste du lapin et j'ai essayé d'autres solutions; essayer de flairer le bon navigateur et la bonne version pour définir correctement les en-têtes est trop un cauchemar. Chrome ne s'identifiait pas correctement comme Safari, qui ne se comporte pas du tout de la même manière (les sauts de virgules ne sont pas encodés correctement). Épargnez-vous la peine, utilisez cette solution et alias l'URL au besoin.
mpen
3
La /:id/:filenameméthode est vraiment simple et fonctionne, merci!
Luca Steeb
2
Mille fois "Oui". Vous gagnerez sérieusement du temps avec cela. Plus encore - certains navigateurs Android vont à plat ignorer la Content-Dispositionet de créer des noms de fichiers très intéressants à la place (ils seront générés à partir de votre chemin). Donc, la seule solution pour garder sa raison est simplement de définir Content-Disposition: attachmentet de passer le nom de fichier souhaité comme dernier composant de chemin:
Julik
73

La RFC 6266 décrit «l' utilisation du champ d'en-tête de disposition de contenu dans le protocole de transfert hypertexte (HTTP) ». Citant de cela:

6. Considérations d'internationalisation

Le filename*paramètre « » ( Section 4.3 ), en utilisant l'encodage défini dans [ RFC5987 ], permet au serveur de transmettre des caractères en dehors du jeu de caractères ISO-8859-1, et également de spécifier éventuellement la langue utilisée.

Et dans leur section d'exemples :

Cet exemple est le même que celui ci-dessus, mais en ajoutant le paramètre "nom de fichier" pour la compatibilité avec les agents utilisateurs n'implémentant pas la RFC 5987 :

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

Remarque: Les agents utilisateurs qui ne prennent pas en charge le codage RFC 5987 ignorent « filename*» lorsqu'il apparaît après « filename».

L' Annexe D contient également une longue liste de suggestions pour accroître l'interopérabilité. Il pointe également vers un site qui compare les implémentations . Les tests passe-partout actuels adaptés aux noms de fichiers courants incluent:

  • attwithisofnplain : nom de fichier ISO-8859-1 simple avec guillemets doubles et sans codage. Cela nécessite un nom de fichier entièrement ISO-8859-1 et ne contenant pas de signes de pourcentage, du moins pas devant les chiffres hexadécimaux.
  • attfnboth : deux paramètres dans l'ordre décrit ci-dessus. Devrait fonctionner pour la plupart des noms de fichiers sur la plupart des navigateurs, bien qu'IE8 utilise le filenameparamètre « ».

Cette RFC 5987 fait à son tour référence à la RFC 2231 , qui décrit le format réel. 2231 est principalement destiné au courrier, et 5987 nous indique quelles parties peuvent également être utilisées pour les en-têtes HTTP. Ne confondez pas cela avec les en-têtes MIME utilisés dans un corpsmultipart/form-data HTTP , qui est régi par la RFC 2388 ( section 4.4 en particulier) et le projet HTML 5 .

MvG
la source
1
J'ai eu des problèmes avec Safari. Lors du téléchargement de fichiers avec des noms russes ont reçu des caractères erronés et illisibles. La solution a aidé. Mais nous devons envoyer un en-tête sur une seule ligne (!!!).
evtuhovdo
16

Le document suivant lié au projet de RFC mentionné par Jim dans sa réponse répond davantage à la question et mérite certainement une note directe ici:

Cas de test pour l'en-tête HTTP Content-Disposition et le codage RFC 2231/2047

Atif Aziz
la source
Notez que l'on peut fournir les deux façons d'encoder le paramètre de nom de fichier, et qu'elles semblent fonctionner correctement avec les anciens navigateurs et les nouveaux navigateurs (l'ancien étant MSIE8 et Safari dans ce cas). Vérifiez attfnboth dans le rapport mentionné par @AtifAziz.
Pablo Montilla
11

dans asp.net mvc2 j'utilise quelque chose comme ceci:

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

Je suppose que si vous n'utilisez pas mvc (2), vous pouvez simplement encoder le nom de fichier en utilisant

HttpUtility.UrlPathEncode(fileName)
Elmer
la source
2
Le codage d'URL pour le codage de nom de fichier n'est pas valide, les navigateurs ne doivent pas décoder ces URL.
2011
IE 11 ne décode certainement pas le codage url dans ce domaine.
pseudocoder
Mais il devait être UrlEncoded lorsque le navigateur est Chrome ou IE, d'autres tels que FF, Safari et Opera fonctionnent bien sans encodage
Reza
11

Mettez le nom de fichier entre guillemets. Résolu le problème pour moi. Comme ça:

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

http://kb.mozillazine.org/Filenames_with_spaces_are_truncated_upon_download

J'ai testé plusieurs options. Les navigateurs ne prennent pas en charge les spécifications et agissent différemment, je pense que les guillemets doubles sont la meilleure option.

Dmitry Kaigorodov
la source
3
Malheureusement, cela ne résout pas tous les problèmes expliqués dans les réponses ci-dessus.
Luca Steeb
2
Cela vous permettra de retourner un nom de fichier avec des espaces, &, %, #etc. Il permet de résoudre cela.
Don Cheadle
Que faire si le nom de fichier contient des guillemets doubles (oui, cela peut arriver), comme spécifié dans la RFC 6266, le nom de fichier est une "chaîne entre guillemets", et comme spécifié dans la RFC 2616, les guillemets doubles dans une chaîne entre guillemets doivent être échappés avec une barre oblique inverse.
Christophe Roussy
10

J'utilise les extraits de code suivants pour l'encodage (en supposant que fileName contient le nom de fichier et l'extension du fichier, c'est-à-dire: 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 + "\"");
Vasilen Donchev
la source
À droite, il devrait être rawurlencodeen PHP au moins pour l'en- filename*=tête de disposition car value-charsutilisé dans la ext-valueRFC 6266-> RFC 5987 (voir tools.ietf.org/html/rfc6266#section-4.1 & tools.ietf.org/html/rfc5987#section -3.2.1 ) n'autorise pas l'espace sans échappement en pourcentage ( filename=, d'autre part, semble qu'il pourrait autoriser un espace sans échapper du tout bien que seul ASCII devrait être présent ici). Il n'est pas nécessaire de coder avec la stricte rigueur du rawurlencode, donc quelques caractères peuvent être échappés
Brett Zamir
9

Dans l'API Web ASP.NET, j'encode le nom de fichier par 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 Non corrigé
IE 9 Fixed

martinoss
la source
5

J'ai testé le code suivant dans tous les principaux navigateurs, y compris les anciens explorateurs (via le mode de compatibilité), et il fonctionne bien partout:

$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.'"');
Stano
la source
5

Je me suis retrouvé avec le code suivant dans mon script "download.php" (basé sur ce blogpost et ces cas de test ).

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

Ceci utilise la manière standard de filename = "..." tant qu'il n'y a que des caractères iso-latin1 et "sûrs" utilisés; sinon, il ajoute le nom de fichier * = UTF-8 '' de manière encodée en url. Selon ce cas de test spécifique , il devrait fonctionner à partir de MSIE9 et sur les versions récentes de FF, Chrome, Safari; sur la version MSIE inférieure, il devrait proposer un nom de fichier contenant la version ISO8859-1 du nom de fichier, avec des traits de soulignement sur les caractères ne figurant pas dans cet encodage.

Note finale: le max. la taille de chaque champ d'en-tête est de 8190 octets sur apache. UTF-8 peut contenir jusqu'à quatre octets par caractère; après rawurlencode, c'est x3 = 12 octets par caractère. Assez inefficace, mais il devrait toujours être théoriquement possible d'avoir plus de 600 "sourires"% F0% 9F% 98% 81 dans le nom de fichier.

apurkrt
la source
... mais la longueur maximale du nom de fichier transférable dépend également du client. Je viens de découvrir qu'au plus [89 sourires sm] .pdf nom de fichier passe par MSIE11. Dans Firefox37, c'est au plus [111x 😁] .pdf. Chrome41 tronque le nom de fichier au 110e sourire. Fait intéressant, le suffixe est transféré correctement.
apurkrt
5

Si vous utilisez un backend nodejs, vous pouvez utiliser le code suivant que j'ai trouvé ici

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);
}
Emanuele Spatola
la source
1
Mieux à utiliser encodeURI(str). Comme exemple avec des dates dans le nom du fichier: 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 1/1/2016"
gdibble
4

En PHP, cela a été fait pour moi (en supposant que le nom de fichier est encodé en UTF8):

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

Testé contre IE8-11, Firefox et Chrome.
Si le navigateur peut interpréter le nom de fichier * = utf-8, il utilisera la version UTF8 du nom de fichier, sinon il utilisera le nom de fichier décodé. Si votre nom de fichier contient des caractères qui ne peuvent pas être représentés dans ISO-8859-1, vous pouvez envisager d'utiliser à la iconvplace.

Gustav
la source
3
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire concernant pourquoi et / ou comment il répond à la question améliorerait considérablement sa valeur à long terme. Veuillez modifier votre réponse pour ajouter des explications.
Toby Speight
2
Whoa, aucune des réponses au code ci-dessus n'a été rejetée ou critiquée comme ça. J'ai également trouvé le pourquoi déjà assez bien répondu: IE n'interprète pas le nom de fichier * = utf-8 mais a besoin de la version ISO8859-1 du nom de fichier, que ce script offre. Je voulais seulement donner aux paresseux un code simple pour PHP.
Gustav
Je pense que cela a été rejeté parce que la question n'est pas spécifique au langage mais sur les RFC à respecter lors de la mise en œuvre de l'encodage d'en-tête. Merci cependant, pour cette réponse, pour PHP, ce code a fait disparaître mes malheurs.
j4k3
Je vous remercie. Cette réponse n'a peut-être pas répondu strictement à la question, mais c'était exactement ce que je cherchais et m'a aidé à résoudre le problème en Python.
Lyndsy Simon
1
Je suis presque sûr que ce code peut être utilisé comme vecteur d'attaque si l'utilisateur peut contrôler le nom du fichier.
Antti Haapala
3

Juste une mise à jour depuis que j'essayais tout ça aujourd'hui en réponse à un problème client

  • À l'exception de Safari configuré pour le japonais, tous les navigateurs testés par nos clients fonctionnaient mieux avec filename = text.pdf - où le texte est une valeur client sérialisée par ASP.Net/IIS dans utf-8 sans encodage d'URL. Pour une raison quelconque, Safari configuré pour l'anglais accepterait et enregistrerait correctement un fichier avec le nom japonais utf-8, mais ce même navigateur configuré pour le japonais enregistrerait le fichier avec les caractères utf-8 sans interprétation. Tous les autres navigateurs testés semblaient fonctionner mieux / bien (quelle que soit la configuration de la langue) avec le nom de fichier utf-8 encodé sans encodage url.
  • Je ne pouvais pas trouver un seul navigateur Rfc5987 mise en œuvre / 8187 du tout . J'ai testé avec les dernières versions de Chrome, Firefox plus IE 11 et Edge. J'ai essayé de définir l'en-tête avec juste le nom de fichier * = utf-8''texturlencoded.pdf, en le définissant avec les deux nom de fichier = text.pdf; nom de fichier * = utf-8''texturlencoded.pdf. Aucune caractéristique de Rfc5987 / 8187 ne semblait être traitée correctement dans aucun des cas ci-dessus.
user1664043
la source
Ceci est une bonne mise à jour. Pouvez-vous élaborer sur les tests spécifiques que vous avez essayés?
Brad
3

Framework PHP Symfony 4 a $filenameFallbackdans HeaderUtils::makeDisposition. Vous pouvez consulter cette fonction pour plus de détails - elle est similaire aux réponses ci-dessus.

Exemple d'utilisation:

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

Solution ASP classique

La plupart des navigateurs modernes prennent en charge le passage Filenamecomme UTF-8maintenant, mais comme c'était le cas avec une solution de téléchargement de fichiers que j'utilise qui était basée sur FreeASPUpload.Net (le site n'existe plus, les liens pointent vers archive.org ), cela ne fonctionnerait pas comme l'analyse du binaire reposait sur la lecture de chaînes codées ASCII à un seul octet, ce qui fonctionnait correctement lorsque vous transmettiez des données codées UTF-8 jusqu'à ce que vous obteniez des caractères ASCII non pris en charge.

Cependant, j'ai pu trouver une solution pour obtenir le code pour lire et analyser le binaire en UTF-8.

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

Le mérite revient à Pure ASP File Upload en implémentant la BytesToString()fonction include_aspuploader.aspdans mon propre code, j'ai pu faire UTF-8fonctionner les noms de fichiers.


Liens utiles

Lankymart
la source
-1

Nous avons eu un problème similaire dans une application Web et nous avons fini par lire le nom de fichier à partir du code HTML <input type="file">et à le définir sous la forme codée par URL dans un nouveau code HTML <input type="hidden">. Bien sûr, nous avons dû supprimer le chemin d'accès comme "C: \ fakepath \" qui est renvoyé par certains navigateurs.

Bien sûr, cela ne répond pas directement à la question des PO, mais peut être une solution pour d'autres.

Andrei I
la source
1
Problème complètement différent. La question concerne le téléchargement , votre réponse concerne le téléchargement .
Oskar Berggren
-3

J'encode normalement l'URL (avec% xx) les noms de fichiers, et cela semble fonctionner dans tous les navigateurs. Vous voudrez peut-être faire des tests de toute façon.

Dario Solera
la source
10
J'en ai testé dans quelques uns et ça ne marche pas comme ça dans tous les navigateurs, donc la question. :)
Atif Aziz