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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用System.IO.Compression在内存中创建ZIP存档相关的知识,希望对你有一定的参考价值。

我正在尝试使用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	est.zip", FileMode.Create))
    {
        stream.CopyTo(fileStream);
    }
}

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

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

using (var fileStream = new FileStream(@"C:Temp	est.zip", FileMode.Create))
using (var archive = new ZipArchive(fileStream, FileMode.Create))
{
    // ...
}

是否可以使用MemoryStream创建没有FileStream的ZIP存档?

答案

感谢https://stackoverflow.com/a/12350106/222748,我得到了:

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	est.zip", FileMode.Create))
   {
      memoryStream.Seek(0, SeekOrigin.Begin);
      memoryStream.CopyTo(fileStream);
   }
}

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

另一答案

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

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();
}
另一答案

在将流复制到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	est.zip", FileMode.Create))
   {
     memoryStream.Position=0;
     memoryStream.WriteTo(fileStream);
   }
 }
另一答案

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

        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	est.zip", FileMode.Create))
            {
                var bytes = memoryStream.GetBuffer();
                fileStream.Write(bytes,0,bytes.Length );
            }
        }
另一答案

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:	est	est.pdf");
        byte[] fileBytes1 = System.IO.File.ReadAllBytes(@"C:	est	est.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);
    }
另一答案
using System;
using System.IO;
using System.IO.Compression;

namespace ConsoleApplication
{
    class Program`enter code here`
    {
        static void Main(string[] args)
        {
            using (FileStream zipToOpen = new FileStream(@"c:usersexampleuser
elease.zip", FileMode.Open))
            {
                using (ZipArchive archive = new ZipArchive(zipToOpen, ZipArchiveMode.Update))
                {
                    ZipArchiveEntry readmeEntry = archive.CreateEntry("Readme.txt");
                    using (StreamWriter writer = new StreamWriter(readmeEntry.Open()))
                    {
                            writer.WriteLine("Information about this package.");
                            writer.WriteLine("========================");
                    }
                }
            }
        }
    }
}
另一答案

这是将实体转换为XML文件然后压缩它的方法:

private  void downloadFile(EntityXML xml) {

string nameDownloadXml = "File_1.xml";
string nameDownloadZip = "File_1.zip";

var serializer = new XmlSerializer(typeof(EntityXML));

Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.AddHeader("content-disposition", "attachment;filename=" + nameDownloadZip);

using (var memoryStream = new MemoryStream())
{
    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
    {
        var demoFile = archive.CreateEntry(nameDownloadXml);
        using (var entryStream = demoFile.Open())
        using (StreamWriter writer = new StreamWriter(entryStream, System.Text.Encoding.UTF8))
        {
            serializer.Serialize(writer, xml);
        }
    }

    using (var fileStream = Response.OutputStream)
    {
        memoryStream.Seek(0, SeekOrigin.Begin);
        memoryStream.CopyTo(fileStream);
    }
}

Response.End();

}

另一答案
       private void button6_Click(object sender, EventArgs e)
    {

        //create With Input FileNames
        AddFileToArchive_InputByte(new ZipItem[]{ new ZipItem( @"E:1.jpg",@"images1.jpg"),
            new ZipItem(@"E:2.txt",@"text2.txt")}, @"C:	est.zip");

        //create with input stream
        AddFileToArchive_InputByte(new ZipItem[]{ new ZipItem(File.ReadAllBytes( @"E:1.jpg"),@"images1.jpg"),
            new ZipItem(File.ReadAllBytes(@"E:2.txt"),@"text2.txt")}, @"C:	est.zip");

        //Create Archive And Return StreamZipFile
        MemoryStream GetStreamZipFile = AddFileToArchive(new ZipItem[]{ new ZipItem( @"E:1.jpg",@"images1.jpg"),
            new ZipItem(@"E:2.txt",@"text2.txt")});


        //Extract in memory
        ZipItem[] ListitemsWithBytes = ExtractItems(@"C:	est.zip");

        //Choese Files For Extract To memory
        List<string> ListFileNameForExtract = new List<string>(new string[] { @"images1.jpg", @"text2.txt" });
        ListitemsWithBytes = ExtractItems(@"C:	est.zip", ListFileNameForExtract);


        // Choese Files For Extract To Directory
        ExtractItems(@"C:	est.zip", ListFileNameForExtract, "c:\extractFiles");

    }

    public struct ZipItem
    {
        string _FileNameSource;
        string _PathinArchive;
        byte[] _Bytes;
        public ZipItem(string __FileNameSource, string __PathinArchive)
        {
            _Bytes=null ;
            _FileNameSource = __FileNameSo

以上是关于使用System.IO.Compression在内存中创建ZIP存档的主要内容,如果未能解决你的问题,请参考以下文章

使用 vb.net 和 System.IO.Compression (.Net 4.5) 压缩文件

我没有在“System.IO.Compression”命名空间中找到“ZipFile”类

System.IO.Compression.ZipFile.CreateFromDirectory - 在 Mac 上打开时没有文件夹结构

使用 System.IO.Compression 压缩 Windows 10 Documents 文件夹,不包括重解析点

ZipFile (System.IO.Compression)、c# (WPF) 的字符提取问题

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