Tôi hiện đang làm việc để di chuyển một vài Bộ điều khiển MVC3 của tôi tới Bộ điều khiển Api MVC4. Tôi đã triển khai Cơ chế nén cho bộ điều khiển MVC3 Nhận phản hồi phương thức bằng cách nhập ActionFilterAttribute
và ghi đè phương thức OnActionExecutiong
. Sau khi một số nghiên cứu tôi thấy rằng tôi cần phải sử dụng ActionFilterMethod
từ System.Web.HttpFilters
. Sẽ rất tuyệt nếu ai đó có thể chia sẻ đoạn mã mẫu để tôi bắt đầu cho phản hồi HTTP nén này bằng GZipNén HTTP GET Response
Trả lời
Cách dễ nhất là enable compression trực tiếp ở cấp IIS.
Nếu bạn muốn làm điều đó ở cấp ứng dụng mà bạn có thể viết một tùy chỉnh ủy xử lý tin nhắn như trong 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();
}
});
}
}
Tất cả những gì còn lại bây giờ là đăng ký xử lý trong Application_Start
:
GlobalConfiguration.Configuration.MessageHandlers.Add(new CompressHandler());
Tôi nghĩ rằng có lỗi trong mã này (cũng như trong các ví dụ tương tự được tìm thấy trên web): Tiêu đề Nội dung Độ dài được đặt không chính xác vì Tiêu đề Nội dung Độ dài được sao chép từ nội dung được nén. Điều này có thể dễ dàng sao chép bằng cách truyền một StringContent thông qua Trình xử lý nén. Để khắc phục điều này, dòng có 'originalContent.Headers' cần được sửa như sau:' originalContent.Headers.Where (x => x.Key! = "Content-Length") ' –
Mã sẽ thất bại nếu không có Accept-Encoding được cung cấp. 'if (response.RequestMessage.Headers.AcceptEncoding! = null)' nên là 'if (response.RequestMessage.Headers.AcceptEncoding.Any())' –
Tôi khuyên bạn nên thêm những điều sau đây trong SendAsync giữa việc gán kiểu mã và gán of response.Content để cho phép các phản hồi lỗi trả về mà không cần nén 'if (response.StatusCode! = HttpStatusCode.OK || response.Content == null || string.IsNullOrWhiteSpace (encodingType)) trả về;' – Paul
Nếu bạn đang sử dụng IIS 7+, tôi sẽ nói nén IIS thành hỗ trợ nén GZIP. Chỉ turn it on.
Mặt khác, quá trình nén quá gần với kim loại cho bộ điều khiển. Bộ điều khiển lý tưởng nên hoạt động ở mức cao hơn nhiều so với byte và luồng.
Nói chung tôi đồng ý, tuy nhiên mức độ nén IIS sẽ yêu cầu cấu hình của bất kỳ máy chủ nào sử dụng nó. – samosaris
Sử dụng một lớp và viết đoạn mã sau
[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);
}
}
Bây giờ hãy tạo một lớp khác và viết mã sau đây.
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();
}
});
}
}
Bây giờ sử dụng thuộc tính sau đây trong điều khiển hoặc trong bất kỳ phương pháp hành động api như thế này
[Route("GetData")]
[CompressFilter]
public HttpResponseMessage GetData()
{
}
Tôi có OWIN Middleware được cấu hình trên API Web của tôi và đây là giải pháp duy nhất có hiệu quả đối với tôi. Ngoài ra, bạn thực sự có thể nhắm mục tiêu những gì bạn muốn nén. Giải pháp tốt! – Elferone
- 1. C# HttpListener Response + GZipStream
- 2. yêu cầu http 'get' của node.js http 'get' với tham số chuỗi truy vấn
- 3. jquery ajax get responseText từ http url
- 4. Nén tiêu đề Http
- 5. Truyền HTTP response, đỏ bừng chuyển sang trình duyệt
- 6. http HEAD with GET performance
- 7. Giải nén phản hồi http đã nén gzip
- 8. Phương thức HTTP GET không được URL này hỗ trợ
- 9. Làm một HTTP GET dưới Qt
- 10. Nhận đối số HTTP GET bằng Python
- 11. SoapHttpClientProtocol log response xml
- 12. Giải nén phản hồi HTTP GZIPed trong Java
- 13. Vấn đề với http GET yêu cầu trên nút js
- 14. Giải nén phản hồi http GZIP http (sử dụng api khách hàng áo, java)
- 15. Giải nén phản hồi http được gzipped
- 16. omniauth mock facebook response
- 17. Groovy HTTPBuilder Mocking the Response
- 18. mã HTTP response để phân biệt giữa các thông số không đúng và giá trị không
- 19. Sử dụng nội dung bố trí trong một tiêu đề HTTP response
- 20. Danh sách toàn diện các mã trạng thái HTTP KHÔNG BAO GỒM MỘT CƠ THỂ RESPONSE
- 21. HTTP 304 Not Modified-response có chứa tiêu đề kiểm soát bộ nhớ cache không?
- 22. Phân tích http GET và POST tham số từ BaseHTTPHandler?
- 23. Phạm vi trong TypeScript/angularJS HTTP GET yêu cầu
- 24. Cách xem yêu cầu GET HTTP cuối cùng trong JavaScript
- 25. Yêu cầu GET HTTP, ASP - Tôi bị mất!
- 26. HTTP GET và POST ngữ nghĩa và hạn chế
- 27. Nginx và favicon.ico - "GET /favicon.ico HTTP/1.1" FAILED
- 28. Android - Đọc một tệp XML có HTTP GET
- 29. Xuân RestTemplate - http GET với yêu cầu cơ thể
- 30. Nhiều thông số HTTP GET với cùng định danh
Tôi đang gặp vấn đề tương tự, mặc dù trong trường hợp của tôi, tôi đã bật tính năng nén IIS. Trong trường hợp của bạn, nó là nén IIS, hay bạn đã tạo trình xử lý tùy chỉnh? – Carvellis
Có, tôi đã sử dụng trình xử lý tùy chỉnh cho điều này giống như cách mà Darin đã đề cập ở đây. –