Я знаю, что это старый пост, но он по-прежнему очень важен. Я обнаружил, что современные браузеры поддерживают rfc5987, что позволяет кодировать utf-8, процент кодируется (кодируется по URL). Тогда Naïve file.txt становится:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (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æøåÆØÅääüïëêîâéíóóúúññ½§! # ¤% & amp; () = `@ £ $ € {[]} +'¨ ^ ~ '-_,;. Txt
В IE7 он работает для некоторых персонажей, но не для всех. Но кто сейчас интересуется IE7?
Это функция, которую я использую для создания безопасных имен файлов для Android. Обратите внимание, что я не знаю, какие символы поддерживаются на Android, но что я проверял, что они работают наверняка:
private static readonly Dictionary 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.
@Alex Жуковский: Я не знаю, почему, но, как обсуждалось в Connect , это не работает ужасно хорошо.