Tôi biết đây là một bài viết cũ nhưng nó vẫn rất liên quan. Tôi đã thấy rằng các trình duyệt hiện đại hỗ trợ rfc5987, cho phép mã hóa utf-8, phần trăm được mã hóa (mã hóa url). Sau đó, tập tin Naïve trở thành:
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) không hỗ trợ này. Thay vào đó, bạn nên sử dụng tiêu chuẩn Safari để viết tên tệp trực tiếp trong tiêu đề được mã hóa utf-8 của bạn:
Content-Disposition: attachment; filename=Naïve file.txt
IE8 trở lên cũng không hỗ trợ nó và bạn cần sử dụng tiêu chuẩn IE của mã hóa utf-8, phần trăm được mã hóa:
Content-Disposition: attachment; filename=Na%C3%AFve%20file.txt
Trong ASP.Net tôi sử dụng mã sau:
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);
Tôi đã thử nghiệm ở trên bằng IE7, IE8, IE9, Chrome 13, Opera 11, FF5, Safari 5.
Cập nhật tháng 11 năm 2013:
Đây là mã tôi hiện đang sử dụng. Tôi vẫn phải hỗ trợ IE8, vì vậy tôi không thể thoát khỏi phần đầu tiên. Hóa ra các trình duyệt trên Android sử dụng trình quản lý tải xuống được tích hợp trong Android và nó không thể phân tích cú pháp tên tệp theo cách tiêu chuẩn.
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);
Hiện tại đã được thử nghiệm trong IE7-11, Chrome 32, Opera 12, FF25, Safari 6, sử dụng tên tệp này để tải xuống: 你好 abcABCæøåÆØÅäöüïëêîâéíáóúýñ½ §! # ¤% & () = `@ £ $ € [[] ^ ~ '-_ ,; txt
Trên IE7 nó hoạt động cho một số ký tự nhưng không phải tất cả. Nhưng ai quan tâm đến IE7 ngày nay?
Đây là chức năng tôi sử dụng để tạo tên tệp an toàn cho Android. Lưu ý rằng tôi không biết những ký tự nào được hỗ trợ trên Android nhưng tôi đã kiểm tra xem những ký tự này có hoạt động không:
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: Tôi đã thử nghiệm trong IE7 và IE8 và hóa ra tôi không cần phải thoát dấu nháy đơn ('). Bạn có một ví dụ mà nó thất bại?
@Dave Van den Eynde: Kết hợp hai tên tệp trên một dòng theo RFC6266 hoạt động ngoại trừ Android và IE7 + 8 và tôi đã cập nhật mã để phản ánh điều này. Cảm ơn vì đã góp ý.
@Thilo: Không có ý tưởng về GoodReader hoặc bất kỳ trình duyệt không phải trình duyệt nào khác. Bạn có thể có một số may mắn khi sử dụng phương pháp Android.
@Alex Zhukovskiy: Tôi không biết tại sao nhưng như đã thảo luận trên Connect, nó dường như không hoạt động tốt lắm.