簡體   English   中英

Content-Disposition 標頭中的 Unicode

[英]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.UrlEncodeServer.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM