Я знаю, что это старый пост, но он все еще очень актуален. Я обнаружил, что современные браузеры поддерживают rfc5987, который допускает кодирование utf-8 в процентах (в кодировке url). Тогда Наивный файл .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 с использованием этого имени файла для загрузки: + ^ ~ -_,;. 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, и оказалось, что мне не нужно избегать апострофа ('). У вас есть пример, где он терпит неудачу?
@ Дэйв Ван ден Эйнде: Объединение двух имен файлов в одной строке, как в соответствии с RFC6266, работает за исключением Android и IE7 + 8, и я обновил код, чтобы отразить это. Спасибо за предложение.
@ Thilo: понятия не имею о GoodReader или любом другом браузере. Возможно, вам повезет, используя подход Android.
@ Alex Zhukovskiy: Я не знаю почему, но, как обсуждалось на Connect , это не очень хорошо работает.