Подтвердить что ты не робот

Создать zip файл из байта []

Я пытаюсь создать Zip файл в .NET 4.5 (System.IO.Compression) из серии байт-массивов. Например, из 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?
4b9b3361

Ответ 1

Немного поиграв и почитав, я смог в этом разобраться. Вот как вы можете создать 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" };
}

Ответ 2

Это вариация большого принятого ответа, опубликованного 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 по ссылкам в принятом ответе, находятся на месте!

Ответ 3

GZipStream и DeflateStream кажутся, что они позволят вам использовать пар/байтовые массивы для решения вашей проблемы, но, возможно, не с форматом файла сжатия, который может использоваться большинством пользователей. (т.е. ваш файл будет иметь расширение .gz). Если этот файл используется только внутри, это может быть все в порядке.

Я не знаю, как вы можете сделать ZIP с помощью библиотек Microsoft, но я помню эту библиотеку, поддерживающую то, что вам может пригодиться: http://sevenzipsharp.codeplex.com/

Он лицензируется под LGPL.