У нас есть страница, на которой пользователи могут загружать носители, и мы создаем структуру папок, подобную следующей, и заносим ее в почтовый ящик и отправляем обратно пользователю в ответ.
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.
Вот еще один способ сделать это с помощью 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: ваш комментарий - извините, не уверен, что он создает что-то в фоновом режиме, но вы не создаете его сами, чтобы что-либо сделать