我需要在内存中创建一个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;
}
这只会创建一个无效的.zip文件,但Windows无法打开该文件。
谢谢!
答案 0 :(得分: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文件写到磁盘中
答案 1 :(得分:2)
您还应该为内部zip文件创建ZipArchive
。将其写入流(memorystream)。然后将此流作为常规流写入主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);
}
}
感谢this的答案。