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-Disposition
tête dans la réponse HTTP du formulaire:
Content-Disposition: attachment; filename=FILENAME
Le filename
paramè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
la source
Content-Disposition: attachment
.Réponses:
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.
la source
Content-Disposition: filename="foo, bar.pdf"
. Le résultat est que Firefox télécharge correctement le fichier mais conserve l'.part
extension (par exemplefoo,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.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:
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:
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é:
Dans ASP.Net, j'utilise le code suivant:
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.
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:
@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.
la source
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt; filename=Na%C3%AFve%20file.txt
et ignorer le reniflement du navigateur? Cela fonctionnerait-il?Il n'existe aucun moyen interopérable de coder les noms non ASCII
Content-Disposition
. La compatibilité du navigateur est un gâchis .La syntaxe théoriquement correcte pour l'utilisation de UTF-8 dans
Content-Disposition
est très bizarre:filename*=UTF-8''foo%c3%a4
(oui, c'est un astérisque, et pas de guillemets sauf un guillemet simple vide au milieu)Cet en-tête n'est pas assez standard (la spécification HTTP / 1.1 reconnaît son existence , mais ne nécessite pas que les clients le prennent en charge).
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:
Et si votre serveur prend en charge la réécriture d'URL (par exemple
mod_rewrite
dans 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:
la source
/:id/:filename
méthode est vraiment simple et fonctionne, merci!Content-Disposition
et 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éfinirContent-Disposition: attachment
et de passer le nom de fichier souhaité comme dernier composant de chemin: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:
Et dans leur section d'exemples :
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:
filename
paramè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 corps
multipart/form-data
HTTP , qui est régi par la RFC 2388 ( section 4.4 en particulier) et le projet HTML 5 .la source
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
la source
dans asp.net mvc2 j'utilise quelque chose comme ceci:
Je suppose que si vous n'utilisez pas mvc (2), vous pouvez simplement encoder le nom de fichier en utilisant
la source
Mettez le nom de fichier entre guillemets. Résolu le problème pour moi. Comme ça:
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.
la source
&
,%
,#
etc. Il permet de résoudre cela.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:
Java:
la source
rawurlencode
en PHP au moins pour l'en-filename*=
tête de disposition carvalue-chars
utilisé dans laext-value
RFC 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ésDans l'API Web ASP.NET, j'encode le nom de fichier par URL:
la source
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:
la source
Je me suis retrouvé avec le code suivant dans mon script "download.php" (basé sur ce blogpost et ces cas de test ).
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.
la source
Si vous utilisez un backend nodejs, vous pouvez utiliser le code suivant que j'ai trouvé ici
la source
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"En PHP, cela a été fait pour moi (en supposant que le nom de fichier est encodé en UTF8):
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
iconv
place.la source
Juste une mise à jour depuis que j'essayais tout ça aujourd'hui en réponse à un problème client
la source
Framework PHP Symfony 4 a
$filenameFallback
dansHeaderUtils::makeDisposition
. Vous pouvez consulter cette fonction pour plus de détails - elle est similaire aux réponses ci-dessus.Exemple d'utilisation:
la source
Solution ASP classique
La plupart des navigateurs modernes prennent en charge le passage
Filename
commeUTF-8
maintenant, 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.
Le mérite revient à Pure ASP File Upload en implémentant la
BytesToString()
fonctioninclude_aspuploader.asp
dans mon propre code, j'ai pu faireUTF-8
fonctionner les noms de fichiers.Liens utiles
Multipart / form-data et UTF-8 dans une application ASP Classic
Différences de format Unicode, UTF, ASCII, ANSI
la source
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.
la source
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.
la source