[英]Using Response.Filter with Response.TransmitFile
我使用Response.Filter以便根據HTTP請求標頭Accept-Encoding
實施流壓縮
這是重要的東西:
if (AcceptEncoding.Contains("deflate") || AcceptEncoding == "*")
{
HttpApp.Response.Filter = new DeflateStream(PreviousOutputStream, CompressionMode.Compress);
HttpApp.Response.AppendHeader("Content-Encoding", "deflate");
}
總的來說,這是可以預期的。 但是,我處於在MVC控制器上使用ActionResult
向用戶代理提供文件的情況下:
Response.Clear();
Response.Headers["Content-Type"] = contentType;
Response.Headers["Content-Length"] = contentLength;
if (Request.QueryString["dl"] == "1")
{
Response.Headers["Content-Disposition"] = "attachment; filename=" + fileInfo.Name;
}
Response.Flush();
Response.TransmitFile(fileInfo.FullName);
更確切地說,該動作方法在Response.TransmitFile()
調用之后返回new EmptyResult()
。 無需修改Response.Filter即可完全按預期工作。
在這種情況下,響應實體到達用戶代理時出現亂碼和難以理解。 FireFox的Poster插件顯示了空的實體或混亂的實體回來。
如果可以幫助,一定要尋找替代方法,因為在ASP.NET中手動進行壓縮並不有趣。 但是,如果您和我一樣頭腦堅定,我謹向您提出以下幾點。
首先:不要使用.NET的內置壓縮流類。 它們有問題,可以隨機截斷流末尾的字節。 我一直在使用DotNetZip並取得良好的效果: http ://dotnetzip.codeplex.com/
現在,一些附加說明:
顯然,圍繞響應過濾和寫入輸出流存在很多不同的問題。 通過使用Reflector和大量實驗,這是到目前為止我發現的最佳解決方案(“在各種情況下都能正常工作”)。
寫一個擴展Encoding的類,並將其稱為BinaryEncoding。 實現所有方法,以便它們正確復制字符和字節,但是當然要進行必要的類型轉換。
將Response.ContentEncoding設置為BinaryEncoding的實例(您可以非常成功地使用單例模式)。
使用FileStream打開文件。
創建一個new StreamReader(fileStream, new BinaryEncoding(), false)
。 該“ false”參數非常重要,它可以阻止StreamReader吃字節順序標記並覆蓋您的BinaryEncoding。
分配char []的緩沖區(我發現32KB是一個不錯的大小)。
然后,在循環中:
int n = StreamReader.Read(buffer, 0, buffer.Length);
Response.Write(buffer, 0, n);
Response.Flush();
直到n為0。
請注意:此方法會導致相當高的CPU使用率。 在100兆LAN上,單個客戶端以10MB /秒的速度下載時,一個內核上的CPU使用率將達到40-50%左右。 我希望我能找到一種更好的方法...如果我擁有Reflector Pro,也許可以找到一個。
如果您使用的是IIS7或IIS7.5,我建議您使用HTTP壓縮模塊,而不要自己動手使用。 這可能有助於解決問題。
http://technet.microsoft.com/zh-cn/library/cc771003(WS.10).aspx
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.