在。net中如何将数据库中的多个文件附加到电子邮件中?我有一个方法,返回一个字节[]包含图像列的内容,我在一个循环调用,以获得每个附件,但我想知道是否有一个"正确"/最佳实践的方式这样做,特别是通过使用MemoryStreams来包含数据引入内存泄漏的可能性?我可以创建一个电子邮件对象并将附件列表附加到它,一旦我得到了它们,就可以很好地处理单个附件,但对于多个文件似乎会变得稍微复杂一些。考虑到我不会认为这是一个不寻常的要求,似乎缺乏关于它的文章/帖子。
Thx - MH
如何继续。假设您有一个从数据库加载的附件数组:
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);
}
事情是这样的:
一个MailMessage
(IDisposable)包含多个Attachments
(IDisposable)。每个附件引用一个MemoryStream
(IDisposable)。MailMessage被封装在using block
中,这确保了它的Dispose方法将被调用,然后调用所有附件的Dispose方法,这些附件又调用内存流的Dispose方法。
嗨,你可以直接从数据库读取缓冲,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...
}
关于如何从数据库中读取字节的类似问题已经被问过无数次了,参见这里的例子:使用SqlDataReader (c#)从SQL Server读取大量字节的最有效方法是什么