Wiem, że to stary post, ale nadal jest bardzo istotny. Przekonałem się, że współczesne przeglądarki obsługują rfc5987, który umożliwia kodowanie utf-8, kodowane procentowo (kodowane w adresie URL). Następnie plik Naïve file.txt staje się:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) nie obsługuje tego. Zamiast tego powinieneś użyć standardu Safari, aby zapisać nazwę pliku bezpośrednio w nagłówku zakodowanym w utf-8:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 i starsze też go nie obsługują i musisz użyć standardu IE kodowania utf-8, zakodowanego procentowo:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
W ASP.Net używam następującego kodu:
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);
Testowałem powyższe przy użyciu IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Aktualizacja z listopada 2013 r .:
Oto kod, którego obecnie używam. Nadal muszę wspierać IE8, więc nie mogę pozbyć się pierwszej części. Okazuje się, że przeglądarki na Androidzie używają wbudowanego menedżera pobierania Androida i nie mogą w niezawodny sposób parsować nazw plików w standardowy sposób.
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);
Powyższe testy zostały teraz przetestowane w IE7-11, Chrome 32, Opera 12, FF25, Safari 6, przy użyciu tej nazwy pliku do pobrania: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýý½!!! # ¤% & () = `@ £ $ {{]] + ´¨ ^ ~ '-_,;. txt
W IE7 działa dla niektórych znaków, ale nie dla wszystkich. Ale kogo dzisiaj obchodzi IE7?
Jest to funkcja, której używam do generowania bezpiecznych nazw plików dla Androida. Pamiętaj, że nie wiem, które znaki są obsługiwane na Androidzie, ale przetestowałem na pewno, czy działają:
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: Testowałem w IE7 i IE8 i okazało się, że nie musiałem uciekać od apostrofu ('). Czy masz przykład, w którym zawodzi?
@Dave Van den Eynde: Łączenie dwóch nazw plików w jednym wierszu zgodnie z RFC6266 działa z wyjątkiem Androida i IE7 + 8, a ja zaktualizowałem kod, aby to odzwierciedlić. Dziękuję za sugestię.
@Thilo: Nie mam pojęcia o GoodReaderze ani żadnej innej przeglądarce. Możesz mieć trochę szczęścia, korzystając z systemu Android.
@Alex Zhukovskiy: Nie wiem dlaczego, ale jak omówiono w Connect , wydaje się, że nie działa to zbyt dobrze.