C# 从字节[]创建zip文件

C# 从字节[]创建zip文件,c#,.net,asp.net-mvc,zip,.net-4.5,C#,.net,Asp.net Mvc,Zip,.net 4.5,我试图在.NET4.5(System.IO.Compression)中从一系列字节数组创建一个Zip文件。例如,从我正在使用的API中,我得到了一个列表,每个附件都有一个名为Body的属性,它是一个字节[]。如何迭代该列表并创建包含每个附件的zip文件 现在我的印象是,我必须将每个附件写入磁盘,并从中创建zip文件 //This is great if I had the files on disk ZipFile.CreateFromDirectory(startPath, zipPath);

我试图在.NET4.5(System.IO.Compression)中从一系列字节数组创建一个Zip文件。例如,从我正在使用的API中,我得到了一个
列表
,每个
附件
都有一个名为
Body
的属性,它是一个
字节[]
。如何迭代该列表并创建包含每个附件的zip文件

现在我的印象是,我必须将每个附件写入磁盘,并从中创建zip文件

//This is great if I had the files on disk
ZipFile.CreateFromDirectory(startPath, zipPath);
//How can I create it from a series of byte arrays?

GZipStream和deflatesttream似乎可以让您使用streams/byte数组来解决问题,但大多数用户可能无法使用压缩文件格式。(即,您的文件将具有.gz扩展名)如果此文件仅在内部使用,则可以

我不知道如何使用Microsoft的库制作ZIP,但我记得这个库支持您可能会发现有用的东西:


它是在LGPL下授权的。

经过一段时间的游戏和阅读,我终于明白了这一点。以下是如何创建包含多个文件的zip文件(存档),而无需将任何临时数据写入磁盘:

using (var compressedFileStream = new MemoryStream())
{
    //Create an archive and store the stream in memory.
    using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create, false)) {
        foreach (var caseAttachmentModel in caseAttachmentModels) {
            //Create a zip entry for each attachment
            var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);

            //Get the stream of the attachment
            using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body))
            using (var zipEntryStream = zipEntry.Open()) {
                //Copy the attachment stream to the zip entry stream
                originalFileStream.CopyTo(zipEntryStream);
            }
        }
    }

    return new FileContentResult(compressedFileStream.ToArray(), "application/zip") { FileDownloadName = "Filename.zip" };
}

这是OP发布的公认答案的变体。然而,这是针对WebForms而不是MVC的。我假设caseAttachmentModel.Body是一个字节[]

本质上,除了一个额外的方法将zip作为响应发送出去外,其他一切都是一样的

using (var compressedFileStream = new MemoryStream()) {
    //Create an archive and store the stream in memory.
    using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Update, false))         {
     foreach (var caseAttachmentModel in caseAttachmentModels) {
        //Create a zip entry for each attachment
        var zipEntry = zipArchive.CreateEntry(caseAttachmentModel.Name);

        //Get the stream of the attachment
        using (var originalFileStream = new MemoryStream(caseAttachmentModel.Body)) {
                using (var zipEntryStream = zipEntry.Open()) {
                    //Copy the attachment stream to the zip entry stream
                    originalFileStream.CopyTo(zipEntryStream);
                }
            }
        }
    }
    sendOutZIP(compressedFileStream.ToArray(), "FileName.zip");
}

private void sendOutZIP(byte[] zippedFiles, string filename)
{
    Response.Clear();
    Response.ClearContent();
    Response.ClearHeaders();
    Response.ContentType = "application/x-compressed";
    Response.Charset = string.Empty;
    Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
    Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);
    Response.BinaryWrite(zippedFiles);
    Response.OutputStream.Flush();
    Response.OutputStream.Close();
    Response.End();
}

我还想指出,@Levi Fuller在被接受的答案中给出的关于推荐人的建议是正确的

您是否查看了中的其他类,特别是那些名称中包含Stream的类@AustinSalonen-我可能遗漏了一些东西,但是,我不认为我可以将多个文件作为GZipStream的输出。我需要的最终结果是多个我不相信GZipStream支持的文件。好的,然后尝试SevenZipSharp。它是围绕7-zip库构建的,但也可以压缩为.zip文件。Codeplex上也可能有类似的库。友好提示-如果ZipArchive类不可用,请添加对程序集的引用:右键单击
引用
->
添加引用
。在
Assemblies
下,搜索
System.IO
并勾选
System.IO.Compression.FileSystem
System.IO.Compression
。什么是caseAttachmentModels?字节[]在哪里?我使用了这个,但是“compressedFileStream”的长度始终为0。。。有什么想法吗?@krillgar你的编辑引入了一个bug。在关闭
zipArchive
后,原始文件具有return语句。通过删除嵌套,您现在还可以在
zipArchive
using
语句中使用return语句。如果不进行处理,则档案无效。@Zeph是正确的。我必须在原始using语句周围添加大括号,并将return语句移出一级以使我的zipArchive有效。我们可以将密码设置为zip文件吗?System.IO.Compression.zipArchive()的文档中没有显示任何为zip文件设置密码的选项。根据这个(旧的)线程()的说法,.NET文件中没有密码功能,建议寻找第三方库。