【问题标题】:ZipArchive created with C# does not contain any entries使用 C# 创建的 ZipArchive 不包含任何条目
【发布时间】:2018-05-14 23:57:42
【问题描述】:

我正在尝试在 ASP.NET MVC 中创建一个压缩文件,其中包含一个 PDF 文件。但是,使用下面的代码会创建一个空的 zip 文件。有人可以告诉我我做错了什么吗?

public FileResult DownloadZipfile(string html)
{
    MemoryStream memoryStream = new MemoryStream();
    ZipArchive archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

    byte[] rawDownload = PDFConverterUtils.PdfSharpConvert(html);

    ZipArchiveEntry entry = archive.CreateEntry("MyPDF.pdf");

    using (Stream entryStream = entry.Open())
    using (StreamWriter streamWriter = new StreamWriter(entryStream))
    {
        streamWriter.BaseStream.Write(rawDownload, 0, rawDownload.Length);
    }

    return new FileStreamResult(memoryStream, System.Net.Mime.MediaTypeNames.Application.Zip) { FileDownloadName = "test.zip" };

}

【问题讨论】:

  • 为什么你有一个没有等待的异步方法?
  • 对不起,谢谢。那是因为为了简洁起见,我删除了优化html 的方法部分。我将编辑方法。
  • 如果您只是将rawDownload 字节写入磁盘,您是否验证了pdf数据?

标签: c# asp.net asp.net-mvc


【解决方案1】:

当使用ZipArchiveMemoryStream 时,我建议在写入流后重置流的位置,以便响应可以读取流的内容。

public FileResult DownloadZipfile(string html) {
    
    byte[] rawDownload = PDFConverterUtils.PdfSharpConvert(html);
    
    MemoryStream memoryStream = new MemoryStream();
    using(ZipArchive archive = new ZipArchive(
        stream: memoryStream, 
        mode: ZipArchiveMode.Create, 
        leaveOpen: true //To leave the memory stream open after disposal
    )){
        ZipArchiveEntry entry = archive.CreateEntry("MyPDF.pdf");
        using (Stream entryStream = entry.Open()) {
            entryStream.Write(rawDownload, 0, rawDownload.Length);
        }
    }
    memoryStream.Position = 0;//reset memory stream position for read
    return new FileStreamResult(memoryStream, System.Net.Mime.MediaTypeNames.Application.Zip) {
        FileDownloadName = "test.zip" 
    };
}

正如另一个答案中所建议的,您应该处理存档以强制其将其内容写入其底层内存流,但请注意以下事项

ZipArchive.Dispose()

除非您使用ZipArchive(Stream, ZipArchiveMode, Boolean) 构造函数重载构造对象并将其leaveOpen 参数设置为true,否则所有底层流都将关闭并且不再可用于后续写入操作。

当您使用完此ZipArchive 实例后,调用Dispose() 以释放此实例使用的所有资源。您应该消除对该ZipArchive 实例的进一步引用,以便垃圾收集器可以回收该实例的内存,而不是保持它处于活动状态以进行终结。

因为你想在写入后使用内存流,你需要确保它保持打开状态,并且流的位置被重置到开头,以便可以读取流的内容从一开始。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-11
    • 2013-02-14
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 2017-07-04
    相关资源
    最近更新 更多