Прикрепление нескольких файлов к электронному письму из колонки изображений базы данных в .NET - PullRequest
4 голосов
/ 06 сентября 2011

Есть ли хорошие примеры того, как прикрепить несколько файлов из базы данных к электронной почте в .NET?У меня есть метод, который возвращает Byte [], содержащий содержимое столбца Image, который я вызываю в цикле, чтобы получить каждое вложение, но мне было интересно, существует ли «правильный» / наилучший способ сделать это, особеннос возможностью введения утечек памяти с помощью MemoryStreams для хранения данных?Я прекрасно создаю объект электронной почты и прикрепляю к нему список вложений, как только я их получу и смогу это сделать с помощью одного вложения, но с несколькими файлами он немного усложняется.Учитывая, что я бы не подумал, что это необычное требование, кажется, не хватает статей / сообщений об этом.

Thx - MH

Ответы [ 2 ]

8 голосов
/ 06 сентября 2011

Вот как это сделать. Предположим, у вас есть массив вложений, загруженных из вашей базы данных:

IEnumerable<byte[]> attachments = ... fetch from your database

Мы могли бы также с уверенностью предположить, что наряду с этими вложениями вы загрузили имена файлов и, возможно, их соответствующий тип MIME (информация, которую вы наверняка должны были сохранить вместе с этими байтовыми массивами, представляющими ваши вложения). Таким образом, вы, вероятно, получили IEnumerable<SomeAttachmentType>, но это не важно для целей этого поста.

Так что теперь вы можете отправить письмо:

using (var client = new SmtpClient("smtp.foo.com"))
using (var message = new MailMessage("from@foo.com", "to@bar.com"))
{
    message.Subject = "test subject";
    message.Body = "test body";
    message.IsBodyHtml = false;
    foreach (var attachment in attachments)
    {
        var attachmentStream = new MemoryStream(attachment);
        // TODO: Choose a better name for your attachments and adapt the MIME type
        var messageAttachment = new Attachment(attachmentStream, Guid.NewGuid().ToString(), "application/octet-stream");
        message.Attachments.Add(messageAttachment);
    }
    client.Send(message);
}

Вот сделка:

A MailMessage (IDisposable) содержит несколько Attachments (IDisposable). Каждое вложение ссылается на MemoryStream (IDisposable). MailMessage заключено в использование block, которое гарантирует, что будет вызван его метод Dispose, который, в свою очередь, вызывает метод Dispose для всех вложений, которые, в свою очередь, вызывают метод Dispose для потоков памяти.

1 голос
/ 06 сентября 2011

Привет, вы можете буферизовать чтения непосредственно из базы данных, MemoryStream НЕ вносит утечку памяти, если вы утилизируете ее после использования. Пример использования SqlDataReader:

using(var stream = new MemoryStream())
{
  byte[] buffer = new byte[4096];

  long l, dataOffset = 0;
  while ((l = reader.GetBytes(columnIndex, dataOffset, buffer, 0, buffer.Length)) > 0)
  {
      stream.Write(buffer, 0, buffer.Length);
      dataOffset += l;
  }

  // here you have the whole stream and can attach it to the email...
}

Подобный вопрос о том, как считывать байты из базы данных, задавался уже бесчисленное количество раз, см. Здесь, например: Какой самый эффективный способ считывать много байтов из SQL Server с использованием SqlDataReader (C #)

...