【问题标题】:Read and Zip entries files in parallel并行读取和压缩条目文件
【发布时间】:2023-01-26 07:11:41
【问题描述】:

我正在尝试从文件列表中并行创建一个 Zip 并将其流式传输到客户端。

我有一个工作代码,我在其中按顺序迭代文件,但我希望它被并行压缩(多个文件每个 >100mb)。

using ZipArchive zipArchive = new(Response.BodyWriter.AsStream(), ZipArchiveMode.Create, leaveOpen: false);

for (int i = 0; i < arrLocalFilesPath.Length; i++) // iterate over files
{
    string strFilePath = arrLocalFilesPath[i]; // list of files path
    string strFileName = Path.GetFileName(strFilePath);

    ZipArchiveEntry zipEntry = zipArchive.CreateEntry(strFileName, CompressionLevel.Optimal);
    using Stream zipStream = zipEntry.Open();

    using FileStream fileStream = System.IO.File.Open(strFilePath, FileMode.Open, FileAccess.Read);
    fileStream.CopyTo(zipStream);
}

return new EmptyResult();

Parallel.ForParallel.ForEach 不适用于ZipArchive

由于ZipArchive 不是线程安全的,我正在尝试使用DotNetZip 来完成此任务。

我查看了docs,这是我目前使用的DotNetZip

using Stream streamResponseBody = Response.BodyWriter.AsStream();

Parallel.For(0, arrLocalFilesPath.Length, i =>
{
    string strFilePath = arrLocalFilesPath[i]; // list of files path
    string strFileName = Path.GetFileName(strFilePath);

    string strCompressedOutputFile = strFilePath + ".compressed";

    byte[] arrBuffer = new byte[8192]; //[4096];
    int n = -1;

    using FileStream input = System.IO.File.OpenRead(strFilePath);
    using FileStream raw = new(strCompressedOutputFile, FileMode.Create, FileAccess.ReadWrite);

    using Stream compressor = new ParallelDeflateOutputStream(raw);
    while ((n = input.Read(arrBuffer, 0, arrBuffer.Length)) != 0)
    {
        compressor.Write(arrBuffer, 0, n);
    }

    input.CopyTo(streamResponseBody);
});

return new EmptyResult();

但是,这不会压缩文件并发送到客户端(它只会在服务器上创建本地 zip 文件)。

使用 MemoryStream 或创建本地 zip 文件是不可能的,也不是我想要的。

服务器应该无缝地流式传输文件的读取字节,即时将其压缩并将其作为块发送给客户端(就像在我的ZipArchive 中一样),但并行读取这些文件并创建它们的 zip 的额外好处。

我知道并行性通常不是 I/O 的最佳选择(有时更糟),但对于这种情况,并行压缩多个大文件应该更快。

我也尝试使用SharpZipLib但没有成功。

使用任何其他库都很好,只要它可以无缝读取文件并将其流式传输到客户端而不影响内存。

任何帮助表示赞赏。

【问题讨论】:

    标签: c# asp.net-core parallel-processing stream zip


    【解决方案1】:

    如果这些文件位于同一驱动器上,则不会有任何加速。并行化用于压缩/解压缩数据,但磁盘IO操作不能并行进行。

    假设文件不在同一个驱动器上,并且有机会加快这个过程......

    你确定 Stream.CopyTo() 是线程安全的吗?检查文档或使用单线程或在其上设置lock

    另外,你有:

    input.CopyTo(streamResponseBody);
    

    应该是:

    compressor.CopyTo(streamResponseBody);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-16
      • 2020-02-12
      • 2012-05-20
      • 1970-01-01
      • 2022-01-06
      • 1970-01-01
      相关资源
      最近更新 更多