C# 从 byte[] 创建 zip 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17217077/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:52:42  来源:igfitidea点击:

Create zip file from byte[]

c#.netasp.net-mvczip.net-4.5

提问by Justin Helgerson

I am trying to create a Zip file in .NET 4.5 (System.IO.Compression) from a series of byte arrays. As an example, from an API I am using I end up with a List<Attachment>and each Attachmenthas a property called Bodywhich is a byte[]. How can I iterate over that list and create a zip file that contains each attachment?

我正在尝试从一系列字节数组在 .NET 4.5 (System.IO.Compression) 中创建一个 Zip 文件。作为一个例子,从API我使用我结束了一个List<Attachment>,并且每个Attachment有一个名为属性Body是一个byte[]。如何遍历该列表并创建一个包含每个附件的 zip 文件?

Right now I am under the impression that I would have to write each attachment to disk and create the zip file from that.

现在我的印象是我必须将每个附件写入磁盘并从中创建 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?

采纳答案by Justin Helgerson

After a little more playing around and reading I was able to figure this out. Here is how you can create a zip file (archive) with multiple files without writing any temporary data to disk:

经过更多的玩耍和阅读后,我能够弄清楚这一点。以下是如何在不将任何临时数据写入磁盘的情况下创建包含多个文件的 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" };
}

回答by Katana314

GZipStream and DeflateStream seem like they would let you use steams/byte arrays to solve your problem, but maybe not with a compression file format usable by most users. (ie, your file would have a .gz extension) If this file is only used internally, that might be okay.

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

I don't know how you might make a ZIP using Microsoft's libraries, but I remember this library supporting the sort of things you might find useful: http://sevenzipsharp.codeplex.com/

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

It's licensed under LGPL.

它是根据 LGPL 许可的。

回答by ShinyCy

This is a variation of the great accepted answer posted by the OP. However, this is for WebForms instead of MVC. I'm working with the assumption that caseAttachmentModel.Body is a byte[]

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

Essentially everything is the same except with an additional method that sends the zip out as a Response.

基本上所有内容都相同,只是有一个额外的方法将 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();
}

I would also like to point out that advice given by @Levi Fuller on references in the accepted answer is spot on!

我还想指出,@Levi Fuller 就已接受答案中的参考文献给出的建议是正确的!