Как сжать данные файла с помощью ICSharpCode.SharpZipLib и загрузить с помощью HttpClient? - PullRequest
0 голосов
/ 08 мая 2020

Я использую ICSharpCode.SharpZipLib и делаю следующее: читаю содержимое файла, сжимаю (zlib) и затем загружаю на сервер с помощью HttpClient.PostAsyn c

Мой обычный подход (как работает для соответствующая загрузка) будет создавать сжатый поток вывода, а затем выполнить Copy / CopyAsyn c из вывода в StreamContent. Однако DeflaterOutputStream не поддерживает чтение, поэтому это не сработает. Как это сделать эффективно? Это может быть только я, но ответ не очевиден.

Я знаю, что могу сначала сжать файл в память (ie. MemoryStream или массив байтов), а затем скопировать их в содержимое http , но это недопустимо

1 Ответ

0 голосов
/ 08 мая 2020

Решением было реализовать абстрактный класс HttpContent, который будет предоставлять доступ к потоку вывода тела http. Важно отметить, что DeflaterOutputStream закроет свой выходной поток при удалении, мы этого не хотим, поэтому необходимо установить IsStreamOwner в false.

using System.IO;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;

public class ZlibContent : HttpContent
{
    private readonly Stream _source;

    public ZlibContent(Stream _source)
    {
        _source = source;
    }

    protected override async Task SerializeToStreamAsync(Stream destinationStream, TransportContext context)
    {
        using (var zlibStream = new DeflaterOutputStream(destinationStream) { IsStreamOwner = false })
        {
            await _source.CopyAsync(zlibStream, this.progress);
        }
    }

    protected override bool TryComputeLength(out long length)
    {
        length = 0;
        return false;
    }
}

Поэтому используйте его следующим образом:

using (var fileStream = /* open file stream */)
using (var content = new ZlibContent(fileStream))
{
    await httpClient.PostAsync("url", content);
}

Таким образом, ключевым моментом является то, что когда сжатый поток (DeflaterOutputStream) находится в «середине», он не копирует из , а копирует в его. .

...