私はこれが古い記事であることを知っていますが、それでもなお非常に関連があります。私は最近のブラウザーがrfc5987をサポートしていることを発見しました。これにより、utf-8エンコード、パーセンテージエンコード(urlエンコード)が可能になります。次に、ナイーブ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以前はそれもサポートしておらず、utf-8エンコードのIE標準を使用する必要があります。
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で説明したように、うまく機能しないようです。