Я знаю, що це стара публікація, але вона все ще дуже актуальна. Я виявив, що сучасні браузери підтримують rfc5987, який дозволяє кодувати utf-8, кодується у відсотках (url-закодованим). Тоді файл Naxt файла.txt стає:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Сафарі (5) цього не підтримує. Натомість слід використовувати стандарт Safari, щоб записати ім'я файлу безпосередньо у закодований заголовок utf-8:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 і старші не підтримують його, і вам потрібно використовувати стандарт IE кодування utf-8, кодований у відсотках:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
У ASP.Net я використовую такий код:
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);
Я тестував вище, використовуючи IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Оновлення листопада 2013 року:
Ось код, яким я зараз користуюся. Я все ще повинен підтримувати IE8, тому я не можу позбутися першої частини. Виявляється, браузери на Android використовують вбудований менеджер завантажень Android, і він не може надійно проаналізувати імена файлів стандартним способом.
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);
Наведене вище тестується в IE7-11, Chrome 32, Opera 12, FF25, Safari 6, використовуючи для завантаження це ім’я файлу: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýý½§! # ¤% & () = `@ £ $ € {[]} + ´¨ ^ ~ '-_,;., txt
У IE7 він працює для деяких символів, але не для всіх. Але кого сьогодні хвилює IE7?
Це функція, яку я використовую для створення безпечних імен файлів для Android. Зауважте, що я не знаю, які символи підтримуються на Android, але я перевірив, що вони працюють точно:
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: Я перевірив IE7 та IE8, і виявилося, що мені не потрібно бігти від апострофа ('). Чи є у вас приклад, коли вона провалюється?
@Dave Van den Eynde: Поєднання двох імен файлів в одному рядку, як це відповідає RFC6266, за винятком Android та IE7 + 8, і я оновив код, щоб це відобразити. Дякую за пропозицію.
@Thilo: Ніякої ідеї про GoodReader чи будь-який інший не-браузер. Можливо, ви пощастить, використовуючи підхід Android.
@ Алекс Жуковський: Я не знаю, чому, але, як обговорювалося на Connect, це, здається, не дуже добре працює.