将IEnumerable转换为内存中的CSV文件,并将其作为附件发送

时间:2016-06-22 15:47:39

标签: c#

我尝试发送包含CSV附件的电子邮件,而不是在我附加文件之前将文件实际写入磁盘。

这是我到目前为止所得到的。

public void EmailBillSiteReport(int billId, string siteNumber)
{
    var bill = GetElectricityBillMain(billId);
    var billSites = bill.ElectricityBillSites.Where(x => x.SiteNo == siteNumber);    
    Helpers.EmailHelper.ConstructAndSendEmail("sample@emailaddress.com", billInvoices.JoinStrings(","));       
}

扩展方法

public static class ListHelper
{
    public static string JoinStrings<T>(this IEnumerable<T> values, string separator)
    {
        var stringValues = values.Select(item =>
        (item == null ? string.Empty : item.ToString()));
        return string.Join(separator, stringValues.ToArray());
    }
}

发送方法

public static void ConstructAndSendEmail(string sendTo, string csv)
{
    System.IO.MemoryStream ms = new System.IO.MemoryStream();
    System.IO.StreamWriter writer = new System.IO.StreamWriter(ms);

    writer.Write(csv);

    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.csv";

    MailMessage md = new MailMessage();

    md.From = new MailAddress("samplefromaddress@email.com");
    md.To.Add(sendTo);

    md.Subject = "sample subject";
    md.Body = "sample body";

    md.Attachments.Add(attach);

    md.IsBodyHtml = false;

    SmtpClient client = new SmtpClient();
    var smtpSection = (SmtpSection)ConfigurationManager.GetSection("system.net/mailSettings/smtp");
    client.Host = smtpSection.Network.Host;
    client.Port = smtpSection.Network.Port;
    client.UseDefaultCredentials = true;
    client.Send(md);

    //close the stream
    writer.Flush();
    writer.Dispose();
    ms.Close();
}

电子邮件带有CSV附件,大小为268字节。其中没有任何内容。我想将我的IEnumerable的内容转换为逗号分隔的字符串并将其作为CSV附加,最好将属性名称保留为标题。我的替代方案是使用LinqToCsv然后先保存文件然后拿起它,但我更喜欢在内存中完成所有操作,因为不需要保存文件。

我在这里做错了什么?

修改

如果我添加Scott Hanselman's ToCsv扩展方法并将其传递到我的ConstructAndSendEmail中,该文件仍然是空的。

1 个答案:

答案 0 :(得分:1)

您必须在使用之前回放流:

writer.Write(csv);
writer.Flush();
ms.Seek(0, SeekOrigin.Begin);

更紧凑的替代方案:

MemoryStream ms =
   new MemoryStream(ASCIIEncoding.Default.GetBytes(csv));

使用这种紧凑的形式,您可以直接将CSV字符串转换为MemoryStream而无需使用Writer。