[英]Unicode in Content-Disposition header
我正在使用在 HttpHandler 子進程中實現的 HttpContext 對象來下載文件,當我的文件名中有非 ascii 字符時,它在 IE 中看起來很奇怪,而在 Firefox 中看起來很好。
以下是代碼:-
context.Response.ContentType = ".cs";
context.Response.AppendHeader("Content-Length", data.Length.ToString());
context.Response.AppendHeader("Content-Disposition", String.Format("attachment; filename={0}",filename));
context.Response.OutputStream.Write(data, 0, data.Length);
context.Response.Flush();
當我在文件名字段中提供 'ß' 'ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü' 'ó' 時,它看起來與我在文件中的不同命名它在 Firefox 中看起來不錯。 添加 EncodingType 和 charset 一直沒有用。
例如,它是 'ß' 'ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü'_'ó',在 Firefox 中它是 'ß' ' ä' 'ö' 'ü' 'ó' 'ß' 'ä' 'ö' 'ü' 'ó'。
知道如何解決這個問題嗎?
我有類似的問題。 您必須使用HttpUtility.UrlEncode或Server.UrlEncode來編碼文件名。 我還記得 Firefox 不需要它。 此外,當它是 url 編碼時,它會破壞文件名。 我的代碼:
// IE needs url encoding, FF doesn't support it, Google Chrome doesn't care
if (Request.Browser.IsBrowser ("IE"))
{
fileName = Server.UrlEncode(fileName);
}
Response.Clear ();
Response.AddHeader ("content-disposition", String.Format ("attachment;filename=\"{0}\"", fileName));
Response.AddHeader ("Content-Length", data.Length.ToString (CultureInfo.InvariantCulture));
Response.ContentType = mimeType;
Response.BinaryWrite(data);
編輯
我已經更仔細地閱讀了規范。 首先, RFC2183指出:
當前的 [RFC 2045] 語法將參數值(以及內容配置文件名)限制為 US-ASCII。
但后來我發現參考文獻 [RFC 2045] 已過時,必須參考RFC 2231 ,其中指出:
星號(“*”)被重用以提供語言和字符集信息存在以及正在使用編碼的指示符。 單引號 ("'") 用於在參數值的開頭分隔字符集和語言信息。 百分號(“%”)用作編碼標志,符合 RFC 2047。
這意味着您可以將 UrlEncode 用於非 ascii 符號,只要您包含rfc中所述的編碼。 下面是一個例子:
string.Format("attachment; filename=\"{0}\"; filename*=UTF-8''{0}", Server.UrlEncode(fileName, Encoding.UTF8));
請注意, filename
中包含除filename*
向后兼容性。 您也可以選擇其他編碼並相應地修改參數,但 UTF-8 涵蓋了所有內容。
HttpUtility.UrlPathEncode 可能是更好的選擇。 由於 URLEncode 將用“+”符號替換空格。
對我來說,這個解決方案適用於所有主要瀏覽器:
Response.AppendHeader("Content-Disposition", string.Format("attachment; filename*=UTF-8''{0}", HttpUtility.UrlPathEncode(fileName).Replace(",", "%2C"));
var mime = MimeMapping.GetMimeMapping(fileName);
return File(fileName, mime);
使用 ASP.NET MVC 3。
替換是必要的,因為 Chrome 不喜歡參數值中的逗號 (,): http : //www.gangarasa.com/lets-Do-GoodCode/tag/err_response_headers_multiple_content_disposition/
您可能需要閱讀RFC 6266並查看http://greenbytes.de/tech/tc2231/上的測試。
對我來說,這解決了這個問題:
var result = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new ByteArrayContent(data)
};
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
{
FileNameStar = "foo-ä-€.html"
};
當我查看 fiddler 中的響應時,我可以看到文件名已使用 UTF-8 自動編碼:
使用 UTF-8 編碼的 Content-Disposition 文件名的 Fiddler 響應示例
如果我們查看 Content-Disposition 標頭的值,我們會發現它與 @Johannes Geyer 的回答相同。 唯一的區別是我們不必自己進行編碼,ContentDispositionHeaderValue 類會負責。
正如 Julian Reschke 所提到的,我在http://greenbytes.de/tech/tc2231/上使用了 Content-Disposition 標頭的測試用例。 可以在 MSDN 上找到有關 ContentDispositionHeaderValue 類的信息。
對於 Asp.Net Core(本文中的第 2 版) UrlPathEncode 已棄用,以下是實現所需結果的方法:
System.Net.Mime.ContentDisposition cd = new System.Net.Mime.ContentDisposition
{
FileName = Uri.EscapeUriString(fileName),
Inline = true // false = prompt the user for downloading; true = browser to try to show the file inline
};
Response.Headers.Add("Content-Disposition", cd.ToString());
我使用Uri.EscapeUriString
將所有字符轉換為它們的十六進制表示,並使用string.Normalize
用於 Unicode 規范化形式 C。(在 ASP.NET MVC5 框架 4.5 中測試)
var contentDispositionHeader = new System.Net.Mime.ContentDisposition
{
Inline = false,
FileName = Uri.EscapeUriString(Path.GetFileName(pathFile)).Normalize()
};
Response.Headers.Add("Content-Disposition", contentDispositionHeader.ToString());
string mimeType = MimeMapping.GetMimeMapping(Server.MapPath(pathFile));
return File(file, mimeType);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.