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.