使用System.IO.Compression在内存中创建ZIP存档

Mar*_*ulz 163 .net c# compression zip ziparchive

我正在尝试使用MemoryStream如下的简单演示文本文件创建ZIP存档:

using (var memoryStream = new MemoryStream())
using (var archive = new ZipArchive(memoryStream , ZipArchiveMode.Create))
{
    var demoFile = archive.CreateEntry("foo.txt");

    using (var entryStream = demoFile.Open())
    using (var streamWriter = new StreamWriter(entryStream))
    {
        streamWriter.Write("Bar!");
    }

    using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
    {
        stream.CopyTo(fileStream);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我运行此代码,则会创建存档文件本身,但不会创建foo.txt.

但是,如果我MemoryStream直接替换文件流,则会正确创建存档:

using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
using (var archive = new ZipArchive(fileStream, FileMode.Create))
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

是否可以使用a MemoryStream创建ZIP存档而不用FileStream

Mic*_*ael 273

感谢/sf/answers/864507451/,我得到了:

using (var memoryStream = new MemoryStream())
{
   using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
   {
      var demoFile = archive.CreateEntry("foo.txt");

      using (var entryStream = demoFile.Open())
      using (var streamWriter = new StreamWriter(entryStream))
      {
         streamWriter.Write("Bar!");
      }
   }

   using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
   {
      memoryStream.Seek(0, SeekOrigin.Begin);
      memoryStream.CopyTo(fileStream);
   }
}
Run Code Online (Sandbox Code Playgroud)

因此我们需要在使用ZipArchive之前调用dispose,这意味着将'true'作为第三个参数传递给ZipArchive,这样我们仍然可以在处理它之后访问它.

  • 似乎ZipArchive在处理时添加校验和并最终确定存档,如果在处置之前使用流,则存档会损坏. (20认同)

小智 46

只是另一个版本的压缩而不写任何文件.

string fileName = "export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".xlsx";
byte[] fileBytes = here is your file in bytes
byte[] compressedBytes;
string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

using (var outStream = new MemoryStream())
{
    using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
    {
        var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Optimal);
        using (var entryStream = fileInArchive.Open())
        using (var fileToCompressStream = new MemoryStream(fileBytes))
        {
            fileToCompressStream.CopyTo(entryStream);
        }
    }
    compressedBytes = outStream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)


Mah*_*esh 13

在将流复制到zip流之前,将流的位置设置为0.

using (var memoryStream = new MemoryStream())
{
 using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
 {
  var demoFile = archive.CreateEntry("foo.txt");

  using (var entryStream = demoFile.Open())
  using (var streamWriter = new StreamWriter(entryStream))
  {
     streamWriter.Write("Bar!");
  }
 }

 using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
   {
     memoryStream.Position=0;
     memoryStream.WriteTo(fileStream);
   }
 }
Run Code Online (Sandbox Code Playgroud)


Rat*_*tle 6

您需要完成写入内存流然后再读取缓冲区.

        using (var memoryStream = new MemoryStream())
        {
            using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create))
            {
                var demoFile = archive.CreateEntry("foo.txt");

                using (var entryStream = demoFile.Open())
                using (var streamWriter = new StreamWriter(entryStream))
                {
                    streamWriter.Write("Bar!");
                }
            }

            using (var fileStream = new FileStream(@"C:\Temp\test.zip", FileMode.Create))
            {
                var bytes = memoryStream.GetBuffer();
                fileStream.Write(bytes,0,bytes.Length );
            }
        }
Run Code Online (Sandbox Code Playgroud)


Deb*_*yay 5

MVC的工作解决方案

    public ActionResult Index()
    {
        string fileName = "test.pdf";
        string fileName1 = "test.vsix";
        string fileNameZip = "Export_" + DateTime.Now.ToString("yyyyMMddhhmmss") + ".zip";

        byte[] fileBytes = System.IO.File.ReadAllBytes(@"C:\test\test.pdf");
        byte[] fileBytes1 = System.IO.File.ReadAllBytes(@"C:\test\test.vsix");
        byte[] compressedBytes;
        using (var outStream = new MemoryStream())
        {
            using (var archive = new ZipArchive(outStream, ZipArchiveMode.Create, true))
            {
                var fileInArchive = archive.CreateEntry(fileName, CompressionLevel.Optimal);
                using (var entryStream = fileInArchive.Open())
                using (var fileToCompressStream = new MemoryStream(fileBytes))
                {
                    fileToCompressStream.CopyTo(entryStream);
                }

                var fileInArchive1 = archive.CreateEntry(fileName1, CompressionLevel.Optimal);
                using (var entryStream = fileInArchive1.Open())
                using (var fileToCompressStream = new MemoryStream(fileBytes1))
                {
                    fileToCompressStream.CopyTo(entryStream);
                }


            }
            compressedBytes = outStream.ToArray();
        }
        return File(compressedBytes, "application/zip", fileNameZip);
    }
Run Code Online (Sandbox Code Playgroud)

  • [`Controller.File` 方法有一个接受 `Stream` 的重载](https://docs.microsoft.com/en-us/dotnet/api/system.web.mvc.controller.file#System_Web_Mvc_Controller_File_System_IO_Stream_System_String_System_String_)。使用它可以避免在内存中创建 ZIP 文件的另一个副本。 (2认同)