PdfGenerator EmailMessage EmailAttachment - 无法访问已关闭的流
PdfGenerator EmailMessage EmailAttachment - Cannot access a closed Stream
尝试附加 System.IO.MemoryStream
EmailAttachment
并将其发送到 EmailMessage
时,抛出错误 System.ObjectDisposedException
和消息 Cannot access a closed Stream
。正在使用 HtmlRenderer.PdfSharp 生成附件。附加和发送是在 using 语句中完成的。
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf("<html><body>foo</body></html>", PdfSharp.PageSize.Letter);
// 2nd argument is to NOT close stream
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
// SiteContext.CurrentSiteName argument is just a site name required for Kentico CMS
// true argument is send immediately
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
如果我改为执行以下操作,只要我不尝试在 try
块内 ms.Dispose()
就不会发生错误:
MemoryStream ms = new MemoryStream();
try
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception)
{
ms.Dispose();
}
第二种方法的问题是 MemoryStream
没有被明确处理。 MemoryStream
是否天生就是用这种方法处理的?如果将 ms.Dispose();
放在 之后,整个块都会发生相同的 Cannot access a closed Stream
。这是等待发生的内存泄漏吗?如何在不关闭流的情况下处理 MemoryStream
以允许电子邮件发送附件?
这是一个需要以某种方式等待 SendEmail()
实际执行其功能的问题吗?
感谢您提供的任何帮助。
我不明白你为什么要在 try 块中处理 ms,通常是为了清理你使用 finally 块的变量,无论是否有异常,它都会被执行。
如果你使用 catch(那种带有 Exception 的 catch 会捕获所有异常)你不会得到错误,因为你正在捕获它们
你应该怎么做:
MemoryStream ms = new MemoryStream();
try
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
ms.Dispose();
}
我能够使用以下代码找到解决方案。关于 SendMail()
的 sendImmediately
参数,它实际上可能更像是一个 Kentico CMS 问题。通过将其设置为 false
(默认),我能够将流作为 EmailAttachment
附加,而不会在 using
语句中出现 System.ObjectDisposedException
错误。
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment.";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
// default sendImmediately of false
EmailSender.SendEmail(SiteContext.CurrentSiteName, em);
}
好吧,您只需要在从 Kentico 访问它之前关闭流,即:
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
pdf.Save(ms, false);
}
然后是电子邮件部分:
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment.";
using (MemoryStream ms = new MemoryStream())
{
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
}
EmailSender.SendEmail(SiteContext.CurrentSiteName, em);
尝试附加 System.IO.MemoryStream
EmailAttachment
并将其发送到 EmailMessage
时,抛出错误 System.ObjectDisposedException
和消息 Cannot access a closed Stream
。正在使用 HtmlRenderer.PdfSharp 生成附件。附加和发送是在 using 语句中完成的。
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf("<html><body>foo</body></html>", PdfSharp.PageSize.Letter);
// 2nd argument is to NOT close stream
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
// SiteContext.CurrentSiteName argument is just a site name required for Kentico CMS
// true argument is send immediately
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
如果我改为执行以下操作,只要我不尝试在 try
块内 ms.Dispose()
就不会发生错误:
MemoryStream ms = new MemoryStream();
try
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception)
{
ms.Dispose();
}
第二种方法的问题是 MemoryStream
没有被明确处理。 MemoryStream
是否天生就是用这种方法处理的?如果将 ms.Dispose();
放在 之后,整个块都会发生相同的 Cannot access a closed Stream
。这是等待发生的内存泄漏吗?如何在不关闭流的情况下处理 MemoryStream
以允许电子邮件发送附件?
这是一个需要以某种方式等待 SendEmail()
实际执行其功能的问题吗?
感谢您提供的任何帮助。
我不明白你为什么要在 try 块中处理 ms,通常是为了清理你使用 finally 块的变量,无论是否有异常,它都会被执行。
如果你使用 catch(那种带有 Exception 的 catch 会捕获所有异常)你不会得到错误,因为你正在捕获它们
你应该怎么做:
MemoryStream ms = new MemoryStream();
try
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.A4);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
EmailSender.SendEmail(SiteContext.CurrentSiteName, em, true);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
ms.Dispose();
}
我能够使用以下代码找到解决方案。关于 SendMail()
的 sendImmediately
参数,它实际上可能更像是一个 Kentico CMS 问题。通过将其设置为 false
(默认),我能够将流作为 EmailAttachment
附加,而不会在 using
语句中出现 System.ObjectDisposedException
错误。
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
pdf.Save(ms, false);
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment.";
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
// default sendImmediately of false
EmailSender.SendEmail(SiteContext.CurrentSiteName, em);
}
好吧,您只需要在从 Kentico 访问它之前关闭流,即:
using (MemoryStream ms = new MemoryStream())
{
var pdf = PdfGenerator.GeneratePdf(html, PdfSharp.PageSize.Letter);
pdf.Save(ms, false);
}
然后是电子邮件部分:
EmailMessage em = new EmailMessage();
em.EmailFormat = EmailFormatEnum.Html;
em.From = "no-reply@foo.com";
em.Recipients = "foo.bar@baz.net";
em.Subject = "Attachment Name";
em.Body = "There is an attachment.";
using (MemoryStream ms = new MemoryStream())
{
var attachment = new EmailAttachment(ms, "foo.pdf");
em.Attachments.Add(attachment);
}
EmailSender.SendEmail(SiteContext.CurrentSiteName, em);