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

我需要在内存中创建一个 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 文件。


提前致谢!


MYYA
浏览 124回答 2
2回答

慕容森

所以我创建了一个 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 文件写入磁盘

蛊毒传说

您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);        }      }
打开App,查看更多内容
随时随地看视频慕课网APP