将 ZipArchive 与 ASP.NET Core Web Api 结合使用

问题描述 投票:0回答:1

问题是如何使用 ASP.NET Core 2(当前)Web API 即时创建压缩(压缩)文件夹?

我正在使用

System.IO.Compression.ZipArchive

我已经发表了几篇博客文章,其中这是使用流或字节数组完成的,所有这些都给了我相同的输出。

我可以下载 zip 文件夹,但无法打开它。

压缩后的文件夹大小正确。虽然打不开。

我希望它工作的方式是让用户单击运行此操作的按钮并返回包含一个或多个文件的压缩文件夹。

[HttpGet]
[Route("/api/download/zip")]
public async Task<IActionResult> Zip()
{
    byte[] bytes = null;

    using (MemoryStream zipStream = new MemoryStream())
    using (var zip = new ZipArchive(zipStream, ZipArchiveMode.Create, true))
    {
        var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");

        // Running just this line gives me the zipped folder (empty) which I can open
        ZipArchiveEntry entry = zip.CreateEntry("File1.pdf", CompressionLevel.Fastest);

        // Adding this 2nd section will download the zip but will not open the zip folder
        using (Stream stream = entry.Open())
        using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read))
        {
            await fs.CopyToAsync(stream);
        }

        bytes = zipStream.ToArray();
    }

    return File(bytes, MediaTypeNames.Application.Zip, $"Attachments{DateTime.Now.ToBinary()}.zip");
}

任何人都可以发现错误或提出替代解决方案吗?

c# asp.net-core asp.net-core-webapi c#-ziparchive
1个回答
7
投票

在处理存档之前,所有数据都不会写入流。因此,在这种情况下,如果存档尚未刷新流中的数据,则流中的数据可能不完整。

在存档有机会将其所有数据刷新到底层流之前,正在调用

memoryStream.ToArray

考虑重构

//...

var tempFileName = await _azure.GetFilesByRef("Azure_FilePath");
using (MemoryStream zipStream = new MemoryStream()) {
    using (var archive = new ZipArchive(zipStream, ZipArchiveMode.Create, leaveOpen: true)) {            
        ZipArchiveEntry entry = archive.CreateEntry("File1.pdf", CompressionLevel.Fastest);    
        using (Stream stream = entry.Open())
        using (FileStream fs = new FileStream(tempFileName, FileMode.Open, FileAccess.Read)) {
            await fs.CopyToAsync(stream);
        }
    }// disposal of archive will force data to be written to memory stream.
    zipStream.Position = 0; //reset memory stream position.
    bytes = zipStream.ToArray(); //get all flushed data
}

//...

您的示例中的假设也是打开的

FileStream
是所创建条目的正确文件类型; 单个 PDF 文件。否则请考虑从
tempFileName
中提取名称。

您必须为要添加到存档中的每个项目添加唯一的条目(文件路径)。

© www.soinside.com 2019 - 2024. All rights reserved.