На сервере в БД хранятся файлы. Необходимо отправлять эти файлы на почту. Я считываю файлы из БД в MemoryStream. Получается, что я имею несколько MemoryStream потоков, каждый из которых является файлом. Мне необходимо заархивировать эти файлы (потоки), что бы потом отправить этот архив вместе с сообщением на почту. Как правильно упаковывать данные файлы(потоки) в архив и указывать правильное расширение этих файлов в архиве, что бы получатель мог разархивировать и открыть данные файлы?
UPD 0. Я могу перевести MemoryStream'ы в массивы байтов, может их можно как то правильно заархивировать?
Вы можете воспользоваться функционалом класса ZipArchive.
Пусть, например, есть два потока
Stream stream1 = new MemoryStream(Encoding.UTF8.GetBytes("Hello"));
Stream stream2 = new MemoryStream(Encoding.UTF8.GetBytes("World"));
Положить их в архив можно так
using (var fileStream = File.Create("Archive.zip"))
using (var zipArchive = new ZipArchive(fileStream, ZipArchiveMode.Create))
{
var zipEntry = zipArchive.CreateEntry("Hello.txt");
using (var zeStream = zipEntry.Open())
stream1.CopyTo(zeStream);
var zipEntry2 = zipArchive.CreateEntry("World.txt");
using (var zeStream = zipEntry2.Open())
stream2.CopyTo(zeStream);
}
В вашем случае, соответственно, будет цикл по потокам.
Если файлы объёмные, то вместо использования MemoryStream целесообразнее может быть протянуть поток напрямую из БД.
Это можно сделать с помощью SqlDataReader. Что-то наподобие
SqlCommand cmd = /* команда для получения данных из БД */;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess))
{
if (reader.Read())
{
int dataFieldIndex = ...;
using (var dataStream = reader.GetStream(dataFieldIndex))
{
var zipEntry = zipArchive.CreateEntry("FileName.ext");
using (var zeStream = zipEntry.Open())
dataStream.CopyTo(zeStream);
}
}
}
Обратите внимание на модификатор CommandBehavior.SequentialAccess у метода ExecuteReader. При его использовании метод GetStream возвращает SqlSequentialStream (внутренний класс в System.Data.SqlClient), который вычитывает данные пакетами по мере необходимости. Если не использовать SequentialAccess, то метод GetStream будет вычитывать данные полностью и возвращать их обёрнутыми в MemoryStream.
Если бинарные данные в БД лежат в столбце с типом varbinary(max) FILESTREAM
, то, вдобавок, можно вытащить их с помощью SqlFileStream.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Нужна помощь, пожалуйстаНужно вычислить idf для конкретного текста в richtexbox (tf есть)
У меня есть класс со свойством типа enum property и при сериализации в json оно выводится как число, в то время как мне надо чтобы результат был в виде...
Знакомлюсь с IoC контейнерами и NinjectПо примерам в сети сделал реализацию для Ninject