Sé que esta es una publicación antigua pero sigue siendo muy relevante. He descubierto que los navegadores modernos son compatibles con rfc5987, que permite la codificación utf-8, codificada en porcentaje (codificada en url). Entonces Naïve file.txt se convierte en:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) no es compatible con esto. En su lugar, debe usar el estándar Safari para escribir el nombre del archivo directamente en su encabezado codificado utf-8:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 y versiones anteriores tampoco lo admiten y debe usar el estándar IE de codificación utf-8, codificado porcentual:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
En ASP.Net utilizo el siguiente código:
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);
Probé lo anterior usando IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Actualización de noviembre de 2013:
Aquí está el código que uso actualmente. Todavía tengo que soportar IE8, así que no puedo deshacerme de la primera parte. Resulta que los navegadores en Android usan el administrador de descargas de Android incorporado y no pueden analizar de manera confiable los nombres de archivos de la manera estándar.
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);
Lo anterior ahora probado en IE7-11, Chrome 32, Opera 12, FF25, Safari 6, usando este nombre de archivo para descargar: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ £ $ € {[]} + ´¨ ^ ~ '-_,;. txt
En IE7 funciona para algunos caracteres pero no para todos. ¿Pero a quién le importa IE7 hoy en día?
Esta es la función que uso para generar nombres de archivos seguros para Android. Tenga en cuenta que no sé qué caracteres son compatibles con Android, pero he probado que estos funcionan con seguridad:
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: Probé en IE7 e IE8 y resultó que no necesitaba escapar del apóstrofe ('). ¿Tienes un ejemplo donde falla?
@Dave Van den Eynde: la combinación de los dos nombres de archivo en una línea de acuerdo con RFC6266 funciona a excepción de Android e IE7 + 8 y he actualizado el código para reflejar esto. Gracias por la sugerencia.
@Thilo: No tengo idea sobre GoodReader o cualquier otro no navegador. Es posible que tenga suerte con el enfoque de Android.
@ Alex Zhukovskiy: No sé por qué, pero como se discutió en Connect , no parece funcionar muy bien.