如何动态地将文件添加到存储在 Azure Blob 存储中的 zip 存档中?

Dav*_*veA 2 c# zip sharpziplib azure azure-storage

我在 Azure 中有一个进程,可以生成大量 pdf 报告文件并将它们存储在 blob 存储中。我不是单独发送所有这些内容的链接,而是生成一个 zip 文件并将此链接发送给用户。

这个过程全部在一个进程中完成,并且一直运行良好。最近,我在将文件添加到 zip 存档时遇到了 OutOfMemory 异常错误,并且我正在努力寻找解决方案。

下面是我用来创建 zip 文件的代码(注意:使用 SharpLibZip 库)。目前,在添加大约 45 个每个文件 (PDF) 大约 3.5Mb 的文件后,它会失败并出现 OutOfMemoryException。当我点击以下行时发生故障:zipStream.PutNextEntry(newEntry)。

有谁知道我如何改进这个过程?压缩文件太小似乎会在这个级别失败。

Using outputMemStream As New MemoryStream()

    Using zipStream As New ICSharpCode.SharpZipLib.Zip.ZipOutputStream(outputMemStream)
          zipStream.SetLevel(7)

          Dim collD3 As UserSurveyReportCollection = GetFileList(RequestID)

          For Each entityD2 As UserSurveyReport In collD3

              Try
                  Dim strF As String = entityD2.FileLocation

                 'Download blob as memorystream and add this stream to the zip file
                 Dim msR As New MemoryStream 
                 msR = objA.DownloadBlobAsMemoryStream(azureAccount, ReportFolder, entityD2.FileName)
                 msR.Seek(0, SeekOrigin.Begin)

                'Determine file name used in zip file archive for item
                 Dim strZipFileName As String = DetermineZipSourceName(entityD2, strFolder, strFileName)

                 'Add MemoryStream to ZipFile Stream
                 Dim newEntry As ICSharpCode.SharpZipLib.Zip.ZipEntry = New ICSharpCode.SharpZipLib.Zip.ZipEntry(strZipFileName)
                 newEntry.DateTime = DateTime.Now

                 zipStream.PutNextEntry(newEntry)
                 msR.CopyTo(zipStream)
                 zipStream.CloseEntry()

                 msR = Nothing
                 zipStream.Flush()

                 intCounter += 1

        End If

    Catch exZip As Exception

    End Try

  Next


    zipStream.IsStreamOwner = False
    zipStream.Finish()
    zipStream.Close()

    outputMemStream.Position = 0

    Dim bytes As Byte() = outputMemStream.ToArray()
    result.Comment = objA.UploadBlob(bytes, azureAccount, ReportFolder, entityReport.FileName).AbsolutePath


    End Using
  End Using
Run Code Online (Sandbox Code Playgroud)

Car*_*arl 5

对于任何使用 C# 并想要将大型 zip 文件写入 blob 存储的人:

var blob = container.GetBlockBlobReference(outputFilename);
using (var stream = await blob.OpenWriteAsync())
using (var zip = new ZipArchive(stream, ZipArchiveMode.Create))
{
    for (int i = 0; i < 2000; i++)
    {
        using (var randomStream = CreateRandomStream(2))
        {
            var entry = zip.CreateEntry($"{i}.zip", CompressionLevel.Optimal);
            using (var innerFile = entry.Open())
            {
                await randomStream.CopyToAsync(innerFile);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这效果出奇的好。当流式传输到 Azure 时,应用程序内存约为 20Mb,CPU 非常低。我已经毫无问题地创建了非常大的输出文件(> 4.5Gb)