Bu eski bir yazı olduğunu biliyorum ama yine de çok alakalı. Modern tarayıcıların utf-8 kodlamasına, yüzde kodlamasına (url kodlu) izin veren rfc5987'yi desteklediğini buldum. Sonra saf file.txt olur:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) bunu desteklemiyor. Bunun yerine, dosya adını doğrudan utf-8 kodlu başlığınıza yazmak için Safari standardını kullanmalısınız:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 ve daha eski sürümleri de desteklemez ve utf-8 kodlamasının IE standardını kullanmanız gerekir, yüzde kodlanmış:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
ASP.Net'te aşağıdaki kodu kullanıyorum:
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);
Yukarıdakileri IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5 kullanarak test ettim.
Kasım 2013 Güncellemesi :
İşte şu anda kullandığım kod. Hala IE8'i desteklemeliyim, bu yüzden ilk kısımdan kurtulamıyorum. Android'deki tarayıcıların yerleşik Android indirme yöneticisini kullandıkları ve dosya adlarını standart şekilde güvenilir bir şekilde ayrıştıramadığı ortaya çıkıyor.
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);
Yukarıdakiler şimdi indirmek için bu dosya adını kullanarak IE7-11, Chrome 32, Opera 12, FF25, Safari 6'da test edildi: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½§! # ¤% & () = `@ @ £ $ € {[]} + ´¨ ^ ~ '-_;. txt
IE7'de tüm karakterler için değil, bazı karakterler için çalışır. Ama günümüzde IE7'yi kim önemsiyor?
Bu, Android için güvenli dosya adları oluşturmak için kullandığım işlevdir. Android'de hangi karakterlerin desteklendiğini bilmediğimi ancak bunların kesin olarak çalıştığını test ettiğimi unutmayın:
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 ve IE8'de test ettim ve kesme işaretinden (') kaçmak zorunda olmadığım ortaya çıktı. Başarısız olduğu bir örneğiniz var mı?
@Dave Van den Eynde: Android ve IE7 + 8 dışında RFC6266'ya uygun olarak iki dosya adını bir satırda birleştirerek bunu yansıtacak kodu güncelledim. Öneri için teşekkürler.
@Thilo: GoodReader veya diğer tarayıcı olmayanlar hakkında hiçbir fikrim yok. Android yaklaşımını kullanma şansınız olabilir.
@Alex Zhukovskiy: Nedenini bilmiyorum ama Connect'te tartışıldığı gibi çok iyi çalışmıyor gibi görünüyor.