用.NET Core Web API从内存流中返回Zip文件

9

我正在尝试在内存中创建一个Zip文件,并将一些其他文件作为条目添加到归档文件中,然后通过Web API控制器返回它,使用以下代码:

try {
    // Create Zip Archive in Memory
    MemoryStream memoryStream = new MemoryStream();
    ZipArchive zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create);
    foreach(Worksheet w in worksheets) {
        string fullPath = Path.Combine(baseFolder, w.FilePathAndName);
        if(System.IO.File.Exists(fullPath)) {
            ZipArchiveEntry f = zipArchive.CreateEntry(w.FileName, CompressionLevel.Fastest);
            using(Stream entryStream = f.Open()) {
                FileStream fileStream = System.IO.File.OpenRead(fullPath);
                await fileStream.CopyToAsync(entryStream);
            }
        }
    }
    memoryStream.Seek(0, SeekOrigin.Begin);
    return File(memoryStream, "application/zip", $"Files.zip");
} catch(Exception e) {
    return StatusCode(500, "Error: Could not generate zip file");
}

这段代码创建并返回了一个zip文件,但是该文件无效。 7-Zip给出了如下错误提示

运行unzip -t Files.zip检测压缩包后得到以下结果:

  End-of-central-directory signature not found.  Either this file is not
  a zipfile, or it constitutes one disk of a multi-part archive.  In the
  latter case the central directory and zipfile comment will be found on
  the last disk(s) of this archive.
note:  Files.zip may be a plain executable, not an archive
unzip:  cannot find zipfile directory in one of Files.zip or
        Files.zip.zip, and cannot find Files.zip.ZIP, period.

.NET Core 3.1.201 版本

2个回答

11

我找到了问题所在。

我需要在调用memoryStream.Seek(0, SeekOrigin.Begin);之前调用zipArchive.Dispose()


1
嘿,谢谢。我遇到了相反的问题,我的ZIP文件可以在7zip中打开,但在文件浏览器中无法打开,而释放我的归档文件就解决了这个问题。 - KingOfKong
谢谢!移动Seek(...)调用到using (var archive = new ZipArchive(...))块外是我之前遗漏的,这正是同样的问题。 - TheMSG
谢谢!我不得不完全删除 memoryStream.Seek([...]),否则它就无法工作。 - Byte

0

另一个选择是在使用子句中使用zipArchive,像这样:

    using (var memoryStream = new MemoryStream())
            {
                using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
                {
                    for (var i = 0; i < images.Count; i++)
                    {
                        var fileInArchive = zipArchive.CreateEntry(fileNames[i], CompressionLevel.Optimal);
                        using (var entryStream = fileInArchive.Open())
                        using (var fileToCompressStream = new MemoryStream(images[i]))
                        {
                            fileToCompressStream.CopyTo(entryStream);
                        }
                    }
                }

                using (var fileStream = new FileStream(zipPath, FileMode.Create))
                {
                    memoryStream.Seek(0, SeekOrigin.Begin);
                    memoryStream.CopyTo(fileStream);
                }
            }

垃圾回收器会在退出 using 代码块且无需显式调用 dispose() 时自动处理它。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接