简体   繁体   English

从 byte[] 创建 zip 文件

[英]Create zip file from byte[]

I am trying to create a Zip file in .NET 4.5 (System.IO.Compression) from a series of byte arrays.我正在尝试从一系列字节数组在 .NET 4.5 (System.IO.Compression) 中创建一个 Zip 文件。 As an example, from an API I am using I end up with a List<Attachment> and each Attachment has a property called Body which is a byte[] .例如,从我使用的 API 中,我最终得到一个List<Attachment>并且每个Attachment都有一个名为Body的属性,它是一个byte[] How can I iterate over that list and create a zip file that contains each attachment?如何遍历该列表并创建一个包含每个附件的 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?

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" };
}

This is a variation of the great accepted answer posted by the OP.这是 OP 发布的公认答案的变体。 However, this is for WebForms instead of MVC.但是,这是针对 WebForms 而不是 MVC。 I'm working with the assumption that caseAttachmentModel.Body is a byte[]我正在假设 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 就已接受答案中的参考文献给出的建议是正确的!

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. GZipStream 和 DeflateStream 似乎可以让您使用流/字节数组来解决您的问题,但可能不是大多数用户可以使用的压缩文件格式。 (ie, your file would have a .gz extension) If this file is only used internally, that might be okay. (即,您的文件将具有 .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 许可的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM