为了账号安全,请及时绑定邮箱和手机立即绑定

C# ZipArchive - 如何在不写入磁盘的情况下嵌套内部 .zip 文件

C# ZipArchive - 如何在不写入磁盘的情况下嵌套内部 .zip 文件

C#
MYYA 2022-12-24 09:56:52
我需要在内存中创建一个 zip 文件,然后将 zip 文件发送给客户端。但是,在某些情况下,创建的 zip 文件需要包含也在内存中生成的其他 zip 文件。例如,文件结构可能如下所示: SendToClient.zip   InnerZip1.zip     File1.xml     File2.xml   InnerZip2.zip     File3.xml     File4.xml我一直在尝试使用 System.IO.Compression.ZipArchive 库。我无法使用 System.IO.Compression.ZipFile 库,因为我项目的 .NET 版本与其不兼容。这是我尝试过的一个例子。public Stream GetMemoryStream() {    var memoryStream = new MemoryStream();    string fileContents = "Lorem ipsum dolor sit amet";    string entryName = "Lorem.txt";    string innerZipName = "InnerZip.zip";    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) {        ZipArchiveEntry entry = archive.CreateEntry(Path.Combine(innerZipName, entryName), CompressionLevel.Optimal);        using (var writer = new StreamWriter(entry.Open())) {             writer.Write(fileContents);        }    }    return memoryStream}但是,这只是将 Lorem.txt 放在名为“Inner.zip”的文件夹中(而不是实际的 zip 文件中)。如果我创建一个名为“Inner.zip”的条目而不写入它,我可以创建一个空的内部 zip 文件。不过,我无法向其中添加任何内容,之后写入名为“Inner.zip\Lorem.txt”的条目只会再次创建一个文件夹(以及同名的空 .zip 文件)。我还尝试创建一个单独的存档,用内存流对其进行序列化,然后将其作为 .zip 写入原始存档。public Stream CreateOuterZip() {    var memoryStream = new MemoryStream();    using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true)) {        ZipArchiveEntry entry = archive.CreateEntry("Outer.zip", CompressionLevel.NoCompression);        using (var writer = new BinaryWriter(entry.Open())) {            writer.Write(GetMemoryStream().ToArray());        }    }    return memoryStream;}不过,这只会创建一个 Windows 不知道如何打开的无效 .zip 文件。提前致谢!
查看完整描述

2 回答

?
慕容森

TA贡献1853条经验 获得超18个赞

所以我创建了一个 FileStream 而不是 MemoryStream,这样可以更轻松地测试代码


public static Stream CreateOuterZip()

        {

            string fileContents = "Lorem ipsum dolor sit amet";


            // Final zip file

            var fs = new FileStream(

                Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "SendToClient.zip"), FileMode.OpenOrCreate);


            // Create inner zip 1

            var innerZip1 = new MemoryStream();

            using (var archive = new ZipArchive(innerZip1, ZipArchiveMode.Create, true))

            {

                var file1 = archive.CreateEntry("File1.xml");

                using (var writer = new BinaryWriter(file1.Open()))

                {

                    writer.Write(fileContents); // Change fileContents to real XML content

                }

                var file2 = archive.CreateEntry("File2.xml");

                using (var writer = new BinaryWriter(file2.Open()))

                {

                    writer.Write(fileContents); // Change fileContents to real XML content

                }

            }


            // Create inner zip 2

            var innerZip2 = new MemoryStream();

            using (var archive = new ZipArchive(innerZip2, ZipArchiveMode.Create, true))

            {

                var file3 = archive.CreateEntry("File3.xml");

                using (var writer = new BinaryWriter(file3.Open()))

                {

                    writer.Write(fileContents); // Change fileContents to real XML content

                }

                var file4 = archive.CreateEntry("File4.xml");

                using (var writer = new BinaryWriter(file4.Open()))

                {

                    writer.Write(fileContents); // Change fileContents to real XML content

                }

            }


            using (var archive = new ZipArchive(fs, ZipArchiveMode.Create, true))

            {

                // Create inner zip 1

                var innerZipEntry = archive.CreateEntry("InnerZip1.zip");

                innerZip1.Position = 0;

                using (var s = innerZipEntry.Open())

                {

                    innerZip1.WriteTo(s);

                }


                // Create inner zip 2

                var innerZipEntry2 = archive.CreateEntry("InnerZip2.zip");

                innerZip2.Position = 0;

                using (var s = innerZipEntry2.Open())

                {

                    innerZip2.WriteTo(s);

                }

            }


            fs.Close();

            return fs; // The file is written, can probably just close this

        }

您显然可以修改此方法以返回 MemoryStream,或将方法更改为 Void 以仅将 zip 文件写入磁盘


查看完整回答
反对 回复 2022-12-24
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

您ZipArchive还应该为内部 zip 文件创建。将其写入流(内存流)。然后将此流作为一般流写入主 zip。


    static Stream Inner() {


      var memoryStream = new MemoryStream();

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


        var demoFile = archive.CreateEntry("foo2.txt");


        using (var entryStream = demoFile.Open())

        using (var streamWriter = new StreamWriter(entryStream)) {

          streamWriter.Write("Bar2!");

        }

      }

      return memoryStream;

    }


    static void Main(string[] args) {


      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!");

          }


          var zip = archive.CreateEntry("inner.zip");

          using (var entryStream = zip.Open()) {

            var inner = Inner();

            inner.Seek(0, SeekOrigin.Begin);

            inner.CopyTo(entryStream);

          }

        }


        using (var fileStream = new FileStream(@"d:\test.zip", FileMode.Create)) {

          memoryStream.Seek(0, SeekOrigin.Begin);

          memoryStream.CopyTo(fileStream);

        }

      }


查看完整回答
反对 回复 2022-12-24
  • 2 回答
  • 0 关注
  • 97 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信