C# 将MemoryStream中的文件附加到C中的邮件消息#
我正在编写一个程序,将文件附加到电子邮件。目前我正在使用C# 将MemoryStream中的文件附加到C中的邮件消息#,c#,email,smtp,memorystream,C#,Email,Smtp,Memorystream,我正在编写一个程序,将文件附加到电子邮件。目前我正在使用FileStream将文件保存到磁盘中,然后使用 System.Net.Mail.MailMessage.Attachments.Add( new System.Net.Mail.Attachment("file name")); 我不想将文件存储在磁盘中,我想将文件存储在内存中,并从内存流将其传递到附件以下是示例代码 System.IO.MemoryStream ms = new System.IO.MemoryStream(
FileStream
将文件保存到磁盘中,然后使用
System.Net.Mail.MailMessage.Attachments.Add(
new System.Net.Mail.Attachment("file name"));
我不想将文件存储在磁盘中,我想将文件存储在内存中,并从内存流将其传递到
附件以下是示例代码
System.IO.MemoryStream ms = new System.IO.MemoryStream();
System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);
writer.Write("Hello its my sample file");
writer.Flush();
writer.Dispose();
ms.Position = 0;
System.Net.Mime.ContentType ct = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);
System.Net.Mail.Attachment attach = new System.Net.Mail.Attachment(ms, ct);
attach.ContentDisposition.FileName = "myFile.txt";
// I guess you know how to send email with an attachment
// after sending email
ms.Close();
编辑1
您可以按System.Net.Mime.MimeTypeNames指定其他文件类型,如System.Net.Mime.MediaTypeNames.Application.Pdf
基于Mime类型您需要在文件名中指定正确的扩展名,例如“myFile.pdf”
我认为此代码将帮助您:
using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Net.Mail;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
MailAddress SendFrom = new MailAddress(txtFrom.Text);
MailAddress SendTo = new MailAddress(txtTo.Text);
MailMessage MyMessage = new MailMessage(SendFrom, SendTo);
MyMessage.Subject = txtSubject.Text;
MyMessage.Body = txtBody.Text;
Attachment attachFile = new Attachment(txtAttachmentPath.Text);
MyMessage.Attachments.Add(attachFile);
SmtpClient emailClient = new SmtpClient(txtSMTPServer.Text);
emailClient.Send(MyMessage);
litStatus.Text = "Message Sent";
}
catch (Exception ex)
{
litStatus.Text = ex.ToString();
}
}
}
因为我在任何地方都找不到对此的确认,所以我测试了处理邮件消息和/或附件对象是否会像我预期的那样处理加载到它们中的流
下面的测试显示,当邮件消息被释放时,用于创建附件的所有流也将被释放。因此,只要您处理邮件消息,创建邮件消息的流就不需要处理
MailMessage mail = new MailMessage();
//Create a MemoryStream from a file for this test
MemoryStream ms = new MemoryStream(File.ReadAllBytes(@"C:\temp\test.gif"));
mail.Attachments.Add(new System.Net.Mail.Attachment(ms, "test.gif"));
if (mail.Attachments[0].ContentStream == ms) Console.WriteLine("Streams are referencing the same resource");
Console.WriteLine("Stream length: " + mail.Attachments[0].ContentStream.Length);
//Dispose the mail as you should after sending the email
mail.Dispose();
//--Or you can dispose the attachment itself
//mm.Attachments[0].Dispose();
Console.WriteLine("This will throw a 'Cannot access a closed Stream.' exception: " + ms.Length);
有点晚-但希望对其他人仍然有用:-
下面是一个简化的代码片段,用于将内存中的字符串作为电子邮件附件发送(在本例中是CSV文件)
StreamWriter和底层流在消息发送后才应被释放(以避免ObjectDisposedException:无法访问关闭的流
)。如果您所做的只是附加一个字符串,则只需两行即可:
mail.Attachments.Add(Attachment.CreateAttachmentFromString("1,2,3", "text/csv");
mail.Attachments.Last().ContentDisposition.FileName = "filename.csv";
我无法使用带有StreamWriter的邮件服务器工作。
我想可能是因为StreamWriter丢失了很多文件属性信息,可能是我们的服务器不喜欢丢失的内容。
通过Attachment.CreateAttachmentFromString(),它创建了我需要的一切,效果非常好
否则,我建议您使用内存流(字节[])打开内存中的文件,并同时跳过StreamWriter。如果您确实要添加.pdf,我发现有必要将内存流的位置设置为零
var memStream = new MemoryStream(yourPdfByteArray);
memStream.Position = 0;
var contentType = new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Application.Pdf);
var reportAttachment = new Attachment(memStream, contentType);
reportAttachment.ContentDisposition.FileName = "yourFileName.pdf";
mailMessage.Attachments.Add(reportAttachment);
我回答这个问题是因为我需要附加一个通过代码生成的Excel文件,该文件可以作为MemoryStream
使用。我可以将它附加到邮件消息中,但它是作为64字节的文件发送的,而不是原来的~6KB。因此,对我有效的解决方案是:
MailMessage mailMessage = new MailMessage();
Attachment attachment = new Attachment(myMemorySteam, new ContentType(MediaTypeNames.Application.Octet));
attachment.ContentDisposition.FileName = "myFile.xlsx";
attachment.ContentDisposition.Size = attachment.Length;
mailMessage.Attachments.Add(attachment);
设置附件.ContentDisposition.Size的值让我发送附件大小正确的邮件。使用其他打开的memorystream:
MVC4 C#控制器中的lauch pdf和send pdf示例
public void ToPdf(string uco, int idAudit)
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename= Document.pdf");
Response.Buffer = true;
Response.Clear();
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.OutputStream.Flush();
}
public ActionResult ToMail(string uco, string filter, int? page, int idAudit, int? full)
{
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
using (var stream = new MemoryStream(bytes))
using (var mailClient = new SmtpClient("**YOUR SERVER**", 25))
using (var message = new MailMessage("**SENDER**", "**RECEIVER**", "Just testing", "See attachment..."))
{
stream.Position = 0;
Attachment attach = new Attachment(stream, new System.Net.Mime.ContentType("application/pdf"));
attach.ContentDisposition.FileName = "test.pdf";
message.Attachments.Add(attach);
mailClient.Send(message);
}
ViewBag.errMsg = "Documento enviado.";
return Index(uco, filter, page, idAudit, full);
}
我正在使用PDF如何将此类型传递给System.Net.Mime.ContentType ct=new System.Net.Mime.ContentType(System.Net.Mime.MediaTypeNames.Text.Plain);您需要使用System.Net.Mime.MediaTypeNames.Application.Pdf
writer.disospose()
对于我的解决方案来说太早了,但所有其他的都是很好的例子。我非常确定应该有一个ms.Position=0代码>创建附件之前。-1此答案使用附件(字符串文件名)构造函数从磁盘加载附件。OP特别声明他不想从磁盘加载。此外,这只是从红天鹅的答案中的链接粘贴的代码副本。attachFile stream也没有处理。对于任何新来者,我的关键是设置stream.position=0代码>+1,以便正确使用(),这是联机示例和代码片段(包括此问题的公认答案)中似乎总是缺少的内容。感谢@m.t.bennet,这也是我的问题设置stream.Position=0
。在这里设置MIME类型实际上做什么?电子邮件客户端应用程序的内容?@xr280xr-正确。此参数实际上不是必需的,但包括它应有助于收件人的电子邮件客户端明智地处理附件。该死,真聪明。一行代码,您可以将图像文件作为附件添加到电子邮件中。好提示!我希望这真的有记录在案。您对这种行为的测试/验证是有用的,但如果没有官方文档,很难相信这种情况会一直存在。不管怎样,谢谢你的测试。很好的努力和研究@Thyminine如果参考源计算的话,它是有记录的。依次呼叫的呼叫,在mimepart中,谢谢。我认为邮件信息应该做到这一点,并且需要做到这一点,因为我在不同的类别中创建信息,而不是在实际发送信息的地方。花几个小时发送pdf,这很有魅力!谢谢这个代码片段对我很有用。stream.Position=0代码>是帮助我的那句话。如果没有它,我的地址只有504字节,安装了一些kbs。这种方法不需要你在发送之前保持流的打开状态,这对我创建电子邮件的方式非常有帮助。非常感谢。
public void ToPdf(string uco, int idAudit)
{
Response.Clear();
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename= Document.pdf");
Response.Buffer = true;
Response.Clear();
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
Response.OutputStream.Write(bytes, 0, bytes.Length);
Response.OutputStream.Flush();
}
public ActionResult ToMail(string uco, string filter, int? page, int idAudit, int? full)
{
//get the memorystream pdf
var bytes = new MisAuditoriasLogic().ToPdf(uco, idAudit).ToArray();
using (var stream = new MemoryStream(bytes))
using (var mailClient = new SmtpClient("**YOUR SERVER**", 25))
using (var message = new MailMessage("**SENDER**", "**RECEIVER**", "Just testing", "See attachment..."))
{
stream.Position = 0;
Attachment attach = new Attachment(stream, new System.Net.Mime.ContentType("application/pdf"));
attach.ContentDisposition.FileName = "test.pdf";
message.Attachments.Add(attach);
mailClient.Send(message);
}
ViewBag.errMsg = "Documento enviado.";
return Index(uco, filter, page, idAudit, full);
}