Клиентская сторона
Если рассматриваемый код является вашим реальным кодом, то есть как минимум две проблемы:
Не ожидал base.SerializeToStreamAsync
Вы создали новую задачу, но не подождали, пока базовый класс завершит запись в сжатый поток в задаче. Таким образом, вы можете отправить непредсказуемый контент на сервер.
Не переопределить Content-Length
MultipartFormDataContent
вычисляет длину контента на основе несжатых данных, так как вы сжали данные, вы должны пересчитать длину сжатых данных.
Честно говоря, я не думаю, что вам нужно наследовать от MultipartFormDataContent
, чтобы сделать их сжатыми. Вместо этого вы можете сжать все MultipartFormDataContent
в оболочке HttpContent
:
public class GzipCompressedContent : HttpContent
{
private readonly HttpContent _content;
public GzipCompressedContent(HttpContent content)
{
// Copy original headers
foreach (KeyValuePair<string, IEnumerable<string>> header in content.Headers)
{
Headers.TryAddWithoutValidation(header.Key, header.Value);
}
Headers.ContentEncoding.Add("gzip");
_content = content;
}
protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context)
{
using (var gzip = new GZipStream(stream, CompressionMode.Compress, true))
{
// Compress the entire original content
await _content.CopyToAsync(gzip);
}
}
protected override bool TryComputeLength(out long length)
{
// Content-Lenght is optional, so set to -1
length = -1;
return false;
}
}
и использовать его:
var test = new TestClass();
using (var client = new HttpClient())
{
var form = new MultipartFormDataContent();
form.Add(new StringContent(JsonConvert.SerializeObject(test)), "value");
var compressed = new GzipCompressedContent(form);
var result = await client.PostAsync(..., compressed);
}
На стороне сервера
Требуется ваш сервер для поддержки сжатого потока.
Например, по умолчанию ASP. NET Core не поддерживает сжатый запрос, если вы отправляете сжатый запрос GZip в приложение ASP. NET Core, вы увидит исключение:
System.IO.IOException: Unexpected end of Stream, the content may have already been read by another component.
at Microsoft.AspNetCore.WebUtilities.MultipartReaderStream.ReadAsync(Byte[] buffer, Int32 offset, Int32 count, CancellationToken cancellationToken)
Вышеуказанное исключение происходит в конвейере вызова действия до того, как произойдет какое-либо действие контроллера. Таким образом, действия контроллера в этом случае не могут быть достигнуты.
Чтобы исправить это, вам нужно включить поддержку распаковки запросов на стороне сервера.
Если вы используете ASP. NET Core этот пакет Nuget .