【问题标题】:Generated zip file with Asp.NET Core gives error Unexpected end of archive使用 Asp.NET Core 生成的 zip 文件会出现错误 Unexpected end of archive
【发布时间】:2022-01-21 11:33:17
【问题描述】:

我正在尝试从存储为 SQL 数据库中的字节数组的文件生成 zip 文件。我正在使用此代码:

public async Task<IActionResult> Download(int id)
{
    var files = this.assignmentsService.GetFilesForAssignment(id).ToList();

    using var memoryStream = new MemoryStream();
    using var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

    foreach (var file in files)
    {
        var zipFile = archive.CreateEntry(file.Name);
        using var streamWriter = new StreamWriter(zipFile.Open());
        streamWriter.Write(file.Content);
    }

    return this.File(memoryStream.ToArray(), "application/zip", "Description.zip");
}

当我运行它时,文件已成功下载,所有文件都在存档中。但是当我尝试打开其中一个时,我收到以下错误:

C:\Users\User\Downloads\Description.zip:存档意外结束

【问题讨论】:

  • 在返回之前尝试手动归档Dispose

标签: c# asp.net-core zip


【解决方案1】:

您应该dispose ZipArchive 以确保它完成写入目标流。您可以通过将 ZipArchive 包装在 using 块中而不是在此处使用 using 声明来做到这一点:

using var memoryStream = new MemoryStream();
using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
    foreach (var file in files)
    {
        var zipFile = archive.CreateEntry(file.Name);
        using var streamWriter = new StreamWriter(zipFile.Open());
        streamWriter.Write(file.Content);
    }
}

return this.File(memoryStream.ToArray(), "application/zip", "Description.zip");

请注意,File 方法也有重载,directly takes a stream。这样,您可以在保持内存流打开的同时对 ZipArchive 使用 using 声明(File() 调用最终会在将流写入 HTTP 响应后将其释放):

var memoryStream = new MemoryStream();
using var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true);

foreach (var file in files)
{
    var zipFile = archive.CreateEntry(file.Name);
    using var streamWriter = new StreamWriter(zipFile.Open());
    streamWriter.Write(file.Content);
}

return File(memoryStream, "application/zip", "Description.zip");

【讨论】:

  • 第一个选项对我有用,但现在还有另一个问题。当我打开一个文本文件时,它会写入: System.Byte[] 而不是文件的内容。除了文本文件,我无法打开。为什么会发生这种情况?
  • @GeorgiKolev StreamWriter.Writestrings 写入流。但似乎原始内容应该是一个字节数组(byte[])。检查您的GetFilesForAssignment 内部file.Content 的来源。很可能在一个字节数组上有一个.ToString() 调用。
  • 我更改了streamWriter.Write(Encoding.UTF8.GetString(file.Content));,它可以完美地处理文本文件,但除了文本文件之外我仍然无法打开。例如,当我尝试打开 .docx 文档时,它会说:我们很抱歉。我们无法打开 Document.docx,因为我们发现其内容有问题。
  • @GeorgiKolev 我建议您将file.Content 更改为字节数组(然后您可以直接写入zipFile.Open() 返回的流,无需StreamWriter)。否则,如果你使用Encoding.UTF8,像你的 docx 这样的二进制文件将无法正确写入。
猜你喜欢
  • 1970-01-01
  • 2011-04-28
  • 1970-01-01
  • 2011-11-16
  • 2017-06-24
  • 2016-10-21
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
相关资源
最近更新 更多