Вложение Zip-файлов и папок в память с использованием библиотеки DotNetZip

1

У нас есть страница, на которой пользователи могут загружать носители, и мы создаем структуру папок, подобную следующей, и заносим ее в почтовый ящик и отправляем обратно пользователю в ответ.

ZippedFolder.zip
    - Folder A
         - File 1
         - File 2
    - Folder B
         - File 3
         - File 4

Существующая реализация, которая выполняет это, временно сохраняет файлы и каталоги в файловой системе, а затем удаляет их в конце. Мы пытаемся уйти от этого и хотим сделать это полностью в памяти.

Я могу успешно создать ZipFile с файлами в нем, но проблема, с которой я столкнулся, - это создать папку A и папку B и добавить к ним файлы, а затем добавить эти две папки в Zip файл.

Как я могу сделать это без сохранения в файловой системе?

Код для простого сохранения потоков файлов в zip файле и последующего задания выходного потока на ответ следующий.

public Stream CompressStreams(IList<Stream> Streams, IList<string> StreamNames, Stream OutputStream = null)
    {
        MemoryStream Response = null;

        using (ZipFile ZippedFile = new ZipFile())
        {
            for (int i = 0, length = Streams.Count; i < length; i++)
            {
                ZippedFile.AddEntry(StreamNames[i], Streams[i]);
            }
            if (OutputStream != null)
            {
                ZippedFile.Save(OutputStream);
            }
            else
            {
                Response = new MemoryStream();
                ZippedFile.Save(Response);
                // Move the stream back to the beginning for reading
                Response.Seek(0, SeekOrigin.Begin);
            }
        }
        return Response;
    }

EDIT Мы используем DotNetZip для библиотеки zipping/unzipping.

Теги:
io
zip
dotnetzip

1 ответ

0

Вот еще один способ сделать это с помощью System.IO.Compression.ZipArchive

public Stream CompressStreams(IList<Stream> Streams, IList<string> StreamNames, Stream OutputStream = null)
    {
        MemoryStream Response = new MemoryStream();

        using (ZipArchive ZippedFile = new ZipArchive(Response, ZipArchiveMode.Create, true))
        {
            for (int i = 0, length = Streams.Count; i < length; i++)
                using (var entry = ZippedFile.CreateEntry(StreamNames[i]).Open())
                {
                    Streams[i].CopyTo(entry);
                }

        }
        if (OutputStream != null)
        {
            Response.Seek(0, SeekOrigin.Begin);
            Response.CopyTo(OutputStream);
        }

        return Response;
    }

и небольшое испытание:

        using (var write = new FileStream(@"C:\users\Public\Desktop\Testzip.zip", FileMode.OpenOrCreate, FileAccess.Write))
        using (var read = new FileStream(@"C:\windows\System32\drivers\etc\hosts", FileMode.Open, FileAccess.Read))
        {
            CompressStreams(new List<Stream>() { read }, new List<string>() { @"A\One.txt" }, write);
        }

re: ваш комментарий - извините, не уверен, что он создает что-то в фоновом режиме, но вы не создаете его сами, чтобы что-либо сделать

  • 0
    вам может понадобиться еще несколько запросов, я не знаю ... например, в for, если есть опасения, что входные потоки могут ожидать посередине ... или до возврата ... Я не знаю наилучшей практики при работе с потоками. Кроме того, есть CopyToAsync, если он умный.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню