web-dev-qa-db-ja.com

byte []からZipファイルを作成します

一連のバイト配列から.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?
45

もう少し遊んで読んだ後、私はこれを理解することができました。一時データをディスクに書き込まずに、複数のファイルを含む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" };
}
80

これは、OPが投稿した広く受け入れられている回答のバリエーションです。ただし、これはMVCではなくWebForms用です。 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から与えられたアドバイスが注目されることを指摘したいと思います。

4
ShinyCy

GZipStreamとDeflateStreamを使用すると、問題を解決するためにスチーム/バイト配列を使用できるように見えますが、ほとんどのユーザーが使用できる圧縮ファイル形式ではできない場合があります。 (つまり、ファイルの拡張子は.gzになります)このファイルが内部でのみ使用されている場合は、問題ないかもしれません。

Microsoftのライブラリを使用してZipを作成する方法はわかりませんが、このライブラリは、役に立つと思われる種類をサポートしていることを覚えています。 http://sevenzipsharp.codeplex.com/

LGPLでライセンスされています。

2
Katana314