これは古い投稿であることは知っていますが、それでも非常に関連性があります。最近のブラウザは rfc5987 をサポートしており、utf-8 エンコーディング、パーセンテージ エンコーディング (url エンコーディング) が可能であることがわかりました。Naïve file.txt は次のようになります。
Content-Disposition: attachment; filename*=UTF-8''Na%C3%AFve%20file.txt
Safari (5) はこれをサポートしていません。代わりに、utf-8 でエンコードされたヘッダーにファイル名を直接書き込む Safari 標準を使用する必要があります。
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 年 11 月の更新:
ここに私が現在使用しているコードがあります。まだ 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 でテストしたところ、アポストロフィ (') をエスケープする必要がないことがわかりました。失敗した例はありますか?
@Dave Van den Eynde: RFC6266 に従って 2 つのファイル名を 1 行に結合すると、Android と IE7+8 以外で機能します。これを反映するようにコードを更新しました。提案していただきありがとうございます。
@Thilo: GoodReader やその他の非ブラウザーについてはわかりません。Android のアプローチを使用すると、運が良いかもしれません。
@Alex Zhukovskiy: 理由はわかりませんが、Connectで説明されているように、うまく機能していないようです。