美好的一天,
我正在尝试将文件流文件附加到发送附件的电子邮件中。场景是,我需要使用FileStream
创建一个文件,然后将其附加到我的电子邮件中。
到目前为止,这是我的示例代码:
用于创建文件:
public FileStream CreateFileStream(){
using (var ms = new MemoryStream())
{
var writer = new StreamWriter(ms);
writer.WriteLine("file content blah blah blahh");
writer.Flush();
//You have to rewind the MemoryStream before copying
ms.Seek(0, SeekOrigin.Begin);
using (var fs = new FileStream("Filename.txt", FileMode.Create))
{
ms.CopyTo(fs);
return fs;
}
}
}
这是我发送电子邮件的示例代码
// attachment
var fileStreamFile = dto.FileStreamFile;
var contentType = new ContentType(MediaTypeNames.Text.Plain);
var attach = new Attachment(dto.FileStreamFile, contentType);
attach.ContentDisposition.FileName = "File.txt";
mail.Attachments.Add(attach);
...
// code for sending here
...
dto.FileStreamFile.Dispose(); // for disposing File Stream
fileStreamFile
不为null,但会引发错误消息,
Handle = 'dto.FileStreamFile.Handle' threw an exception of type 'System.ObjectDisposedException'
当我注释掉附加代码时,无论如何,电子邮件发送仍然可以正常工作。当我包含附加FileStream
请帮忙吗?预先谢谢你
答案 0 :(得分:4)
您的代码
using (var fs = new FileStream("Filename.txt", FileMode.Create))
{
ms.CopyTo(fs);
return fs; // you are returning here
} // hang on, this is a using statement which will dispose fs!
将翻译为此
FileStream fileStream = new FileStream("Filename.txt", FileMode.Create);
try
{
return fileStream;
}
finally
{
if (fileStream != null)
{
((IDisposable)fileStream).Dispose();
}
}
请注意,如果您在return
中try finally
,它将返回值存储在局部变量中,以便在finally
之后返回。看起来像这样
FileStream fileStream = new FileStream("Filename.txt", FileMode.Create);
try
{
temp = fileStream;
}
finally
{
if (fileStream != null)
{
((IDisposable)fileStream).Dispose();
}
}
return temp;
我们可以看看 IL 看看发生了什么
IL_0000: ldstr "someFile"
IL_0005: ldc.i4.2
IL_0006: newobj instance void [mscorlib]System.IO.FileStream::.ctor(string, valuetype[mscorlib]System.IO.FileMode)
// stloc.0 Pops the current value from the top of the evaluation stack and stores it in the
// local variable list at a specified index. This is your fs reference
IL_000b: stloc.0
.try
{
// ldloc.0 Loads the local variable at a specific index onto the evaluation stack.
// This is your fs reference
IL_000c: ldloc.0
// stloc.1 Pops the current value from the top of the evaluation stack and stores it in
// the local variable list at a specified index. This is your fs reference
IL_000d: stloc.1
IL_000e: leave.s IL_001a
} // end .try
finally
{
IL_0010: ldloc.0
IL_0011: brfalse.s IL_0019
IL_0013: ldloc.0
// oh no we just Disposed fs!!!
IL_0014: callvirt instance void [mscorlib]System.IDisposable::Dispose()
IL_0019: endfinally
} // end handler
// ldloc.1 Loads the local variable at a specific index onto the evaluation stack.
// This is your fs reference
IL_001a: ldloc.1
//ret Returns from the current method, pushing a return value (if present) from
//the callee's evaluation stack onto the caller's evaluation stack.
IL_001b: ret
简而言之,不要从IDisposable
语句返回using
引用,因为它会被处置。
您将需要创建FileStream
(无using
)和Dispose
在另一个上下文中,或重构您的代码。
更新
但是在我写了一条using语句后,我的电子邮件发送不起作用 通过流覆盖发送电子邮件
您可能将其复杂化了,尝试这样的事情
using (var stream = new MemoryStream())
using (var writer = new StreamWriter(stream)) // using UTF-8 encoding by default
using (var mailClient = new SmtpClient("localhost", 25))
using (var message = new MailMessage("me@example.com", "you@example.com", "Just testing", "See attachment..."))
{
writer.WriteLine("file content blah blah blahh");
writer.Flush();
stream.Position = 0; // read from the start of what was written
message.Attachments.Add(new Attachment(stream, "filename.csv", "text/csv"));
mailClient.Send(message);
}