我目前正致力於將少數MVC3控制器遷移到MVC4 Api控制器。 我已經實現了MVC3控制器獲取方法響應的壓縮機制,通過調用ActionFilterAttribute
並覆蓋OnActionExecutiong
方法。經過一些研究後,我發現我需要使用從System.Web.HttpFilters
。這將是巨大的,如果有人可以分享一段示例代碼,讓我開始了使用gzip壓縮HTTP GET響應
回答
最簡單的是enable compression直接IIS水平。
如果你想在應用層面做到這一點,你可以寫一個自定義委託消息處理程序如圖所示following post:
public class CompressHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>((responseToCompleteTask) =>
{
HttpResponseMessage response = responseToCompleteTask.Result;
if (response.RequestMessage.Headers.AcceptEncoding != null)
{
string encodingType = response.RequestMessage.Headers.AcceptEncoding.First().Value;
response.Content = new CompressedContent(response.Content, encodingType);
}
return response;
},
TaskContinuationOptions.OnlyOnRanToCompletion);
}
}
public class CompressedContent : HttpContent
{
private HttpContent originalContent;
private string encodingType;
public CompressedContent(HttpContent content, string encodingType)
{
if (content == null)
{
throw new ArgumentNullException("content");
}
if (encodingType == null)
{
throw new ArgumentNullException("encodingType");
}
originalContent = content;
this.encodingType = encodingType.ToLowerInvariant();
if (this.encodingType != "gzip" && this.encodingType != "deflate")
{
throw new InvalidOperationException(string.Format("Encoding '{0}' is not supported. Only supports gzip or deflate encoding.", this.encodingType));
}
// copy the headers from the original content
foreach (KeyValuePair<string, IEnumerable<string>> header in originalContent.Headers)
{
this.Headers.AddWithoutValidation(header.Key, header.Value);
}
this.Headers.ContentEncoding.Add(encodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
if (encodingType == "gzip")
{
compressedStream = new GZipStream(stream, CompressionMode.Compress, leaveOpen: true);
}
else if (encodingType == "deflate")
{
compressedStream = new DeflateStream(stream, CompressionMode.Compress, leaveOpen: true);
}
return originalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
}
所有,現在剩下的就是註冊在Application_Start
處理程序:
GlobalConfiguration.Configuration.MessageHandlers.Add(new CompressHandler());
我認爲這個代碼中存在一個錯誤(以及在網上找到的類似例子):內容長度標題設置不正確,因爲內容長度標題是從壓縮內容複製的。通過傳遞一個StringContent到壓縮處理程序,可以很容易地重現這一點。爲了解決這個問題,帶有'originalContent.Headers'的行需要像這樣修復:'originalContent.Headers.Where(x => x.Key!=「Content-Length」)' –
如果沒有Accept-Encoding被提供。 '如果(response.RequestMessage.Headers.AcceptEncoding!= NULL)'應該是'如果(response.RequestMessage.Headers.AcceptEncoding.Any())' –
我會建議增加在SendAsync編碼類型和分配的分配之間的以下response.Content的允許誤差響應無壓縮返回'如果(!response.StatusCode = HttpStatusCode.OK || response.Content == NULL || string.IsNullOrWhiteSpace(編碼類型))返回響應;' – Paul
如果您使用的是IIS 7+這個壓縮HTTP響應,我會說離開壓縮到IIS,因爲它支持gzip壓縮。只需turn it on。
在另一方面,壓縮是太靠近金屬爲控制器。理想情況下,控制器應該比字節和數據流工作在更高的水平。
總的來說,我同意,但是IIS級別的壓縮需要配置使用它的任何服務器。 – samosaris
使用一個類,並用下面的代碼
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CompressFilter : ActionFilterAttribute
{
public override void OnActionExecuted(HttpActionExecutedContext context)
{
var acceptedEncoding = context.Response.RequestMessage.Headers.AcceptEncoding.First().Value;
if (!acceptedEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase)
&& !acceptedEncoding.Equals("deflate", StringComparison.InvariantCultureIgnoreCase))
{
return;
}
context.Response.Content = new CompressedContent(context.Response.Content, acceptedEncoding);
}
}
現在創建另一個類並編寫下面的代碼。
public class CompressedContent : HttpContent
{
private readonly string _encodingType;
private readonly HttpContent _originalContent;
public CompressedContent(HttpContent content, string encodingType = "gzip")
{
if (content == null)
{
throw new ArgumentNullException("content");
}
_originalContent = content;
_encodingType = encodingType.ToLowerInvariant();
foreach (var header in _originalContent.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.ContentEncoding.Add(encodingType);
}
protected override bool TryComputeLength(out long length)
{
length = -1;
return false;
}
protected override Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
Stream compressedStream = null;
switch (_encodingType)
{
case "gzip":
compressedStream = new GZipStream(stream, CompressionMode.Compress, true);
break;
case "deflate":
compressedStream = new DeflateStream(stream, CompressionMode.Compress, true);
break;
default:
compressedStream = stream;
break;
}
return _originalContent.CopyToAsync(compressedStream).ContinueWith(tsk =>
{
if (compressedStream != null)
{
compressedStream.Dispose();
}
});
}
}
現在使用下面的屬性,控制器或任何API操作方法是這樣
[Route("GetData")]
[CompressFilter]
public HttpResponseMessage GetData()
{
}
我的Web API上配置了OWIN中間件,這是唯一適用於我的解決方案。另外,你可以真正地定位你想要壓縮的東西。好解決方案! – Elferone
- 1. 壓縮HTTP響應頭?
- 2. 壓縮HTTP響應?可能?
- 3. 解壓縮gzip http響應
- 4. MVC4 WebAPI不壓縮GET響應
- 5. GET HTTP響應
- 6. 在Vim中解壓縮gzip http響應
- 7. 如何使用mongrel壓縮http響應
- 8. 在Java中解壓縮GZIPed HTTP響應
- 9. 如何壓縮HTTP響應頭文件?
- 10. Net :: HTTP不會自動解壓縮壓縮響應
- 11. AngularJs HTTP GET響應
- 12. HTTP GET檢索壓縮文件
- 13. 如何使用zlib爲HTTP壓縮HTTP響應?
- 14. Http GET響應時間
- 15. 德爾福GET HTTP響應
- 16. Libevent HTTP Server&壓縮?
- 17. WCF壓縮JSON響應
- 18. Azure DocumentDb壓縮/ gzip響應
- 19. ASP.NET WebService響應壓縮
- 20. 壓縮JSON響應PHP
- 21. GZip壓縮的REST響應
- 22. Web服務響應壓縮
- 23. android httprequest壓縮響應
- 24. 如何壓縮JSON響應
- 25. 集成測試支持流式gzip壓縮http響應的庫
- 26. 解壓縮GZIP http響應(使用jersey客戶端api,java)
- 27. 如何使用gzip壓縮讀取HTTP響應?
- 28. GZIPOutputStream未正確壓縮HTTP響應的字符串
- 29. 如何通過ngrep解壓縮HTTP響應正文?
- 30. 如何確定HTTP請求/響應是否在IE7中壓縮?
我有同樣的問題,雖然在我的情況我已經啓用IIS壓縮。在你的情況下,它是IIS壓縮,還是你創建自定義處理程序? – Carvellis
是的,我已經使用自定義處理程序,就像Darin在這裏提到的方式。 –