从byte []创建zip文件

时间:2013-06-20 14:59:10

标签: c# .net asp.net-mvc zip .net-4.5

我正在尝试从一系列字节数组中创建.NET 4.5(System.IO.Compression)中的Zip文件。例如,在我使用的API中,我最终得到List<Attachment>,每个Attachment都有一个名为Body的属性byte[]。如何迭代该列表并创建包含每个附件的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?

3 个答案:

答案 0 :(得分:76)

经过多一点的游戏和阅读后,我能够弄清楚这一点。以下是如何创建包含多个文件的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);
        }
    }

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

答案 1 :(得分:4)

这是OP公布的最受欢迎的答案的变体。但是,这适用于WebForms而不是MVC。我正在假设caseAttachmentModel.Body是一个byte []

基本上一切都是相同的,除了使用另一种方法将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在接受的答案中提供的建议是现实的!

答案 2 :(得分:2)

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

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

它是根据LGPL许可的。