将RDLC输出分发为电子邮件附件

时间:2010-10-03 09:43:42

标签: winforms rdlc .emf

我们的winforms应用程序长期允许“打印”选项,基本上使用RDLC。

客户要求我们添加一项功能,允许用户通过电子邮件发送“打印”输出。

现在,我们知道创建了一个EMF文件(在TEMP文件夹中),作为当前打印过程的一种隐藏副产品。

在我们看来,我们可以直接获取此EMF文件并将其附加到新电子邮件中,然后完成工作。

  1. 这是最好的选择吗?
  2. 我们可以依赖任何Windows机器打开的EMF文件吗?
  3. 我们如何识别EMF文件? ...目前似乎只是命名为 %TEMP%\DiaryGrid_1.emf 。好的,所以DiaryGrid是我们的RDLC文件的名称,但_1被添加到某个地方。

1 个答案:

答案 0 :(得分:8)

我之前做过。我以编程方式将报告导出到pdf到特定位置,然后我们通过电子邮件发送pdf文件并将其删除。我将尝试为您找到代码(现在不在家)

<强>编辑:

对不起。现在我在家里,我会给你一些代码块,我认为这会给你一些帮助来完成你的任务。我将在代码中包含一些注释,以便您了解我的项目中特定的一些内容。这段代码经过测试,在我的客户端运行良好,但我确信它可以改进。如果您可以改进此代码,请告诉我们;)

首先,我们将报告导出为pdf。

private string ExportReportToPDF(string reportName)
{
   Warning[] warnings;
   string[] streamids;
   string mimeType;
   string encoding;
   string filenameExtension;
   byte[] bytes = ReportViewer1.LocalReport.Render(
      "PDF", null, out mimeType, out encoding, out filenameExtension,
       out streamids, out warnings);

   string filename = Path.Combine(Path.GetTempPath(), reportName);
   using (var fs = new FileStream(filename, FileMode.Create))
   {
      fs.Write(bytes, 0, bytes.Length);
      fs.Close();
   }

   return filename;
}

现在,我们需要一个控制Mail系统的类。每个邮件系统都有自己的特性,所以也许你需要修改这个类。这个类的行为很简单。您只需要填充属性,然后调用Send方法。在我的情况下,Windows发送后不允许我删除pdf文件(Windows说该文件正在使用中),所以我在下次重启时编写要删除的文件。看看删除方法。请注意,send方法使用名为MailConfig的cutom类。这是一个小类,它有一些配置字符串,如主机,用户名和密码。邮件将使用此参数发送。

public class Mail
{
   public string Title { get; set; }
   public string Text { get; set; }
   public string From { get; set; }
   public bool RequireAutentication { get; set; }
   public bool DeleteFilesAfterSend { get; set; }

   public List<string> To { get; set; }
   public List<string> Cc { get; set; }
   public List<string> Bcc { get; set; }
   public List<string> AttachmentFiles { get; set; }

   #region appi declarations

   internal enum MoveFileFlags
   {
      MOVEFILE_REPLACE_EXISTING = 1,
      MOVEFILE_COPY_ALLOWED = 2,
      MOVEFILE_DELAY_UNTIL_REBOOT = 4,
      MOVEFILE_WRITE_THROUGH = 8
   }

   [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
   static extern bool MoveFileEx(string lpExistingFileName,
                                 string lpNewFileName,
                                 MoveFileFlags dwFlags);

   #endregion

   public Mail()
   {
      To = new List<string>();
      Cc = new List<string>();
      Bcc = new List<string>();
      AttachmentFiles = new List<string>();
      From = MailConfig.Username;
   }

   public void Send()
   {
      var client = new SmtpClient
      {
         Host = MailConfig.Host,
         EnableSsl = false,
      };

      if (RequireAutentication)
      {
         var credentials = new NetworkCredential(MailConfig.Username, 
                                                 MailConfig.Password);
         client.Credentials = credentials;
      }

      var message = new MailMessage
      {
         Sender = new MailAddress(From, From),
         From = new MailAddress(From, From)
      };

      AddDestinataryToList(To, message.To);
      AddDestinataryToList(Cc, message.CC);
      AddDestinataryToList(Bcc, message.Bcc);

      message.Subject = Title;
      message.Body = Text;
      message.IsBodyHtml = false;
      message.Priority = MailPriority.High;

      var attachments = AttachmentFiles.Select(file => new Attachment(file));
      foreach (var attachment in attachments)
         message.Attachments.Add(attachment);

      client.Send(message);

      if (DeleteFilesAfterSend)
         AttachmentFiles.ForEach(DeleteFile);
   }

   private void AddDestinataryToList(IEnumerable<string> from,
      ICollection<MailAddress> mailAddressCollection)
   {
      foreach (var destinatary in from)
         mailAddressCollection.Add(new MailAddress(destinatary, destinatary));
   }

   private void DeleteFile(string filepath)
   {
      // this should delete the file in the next reboot, not now.
      MoveFileEx(filepath, null, MoveFileFlags.MOVEFILE_DELAY_UNTIL_REBOOT);
   }
}

现在,您可以创建一个表单来询问目的地,添加一些验证等,返回给您一个Mail类的实例......或者您可以简单地“硬编码”这些值并填充该类。< / p>

以下是我在按钮中使用的代码来调用此表单,在我的示例中,它名为SendMailView。

private void BtnSendByMail_Click(object sender, EventArgs e)
{
   SendMailView sendMailView = new SendMailView();

   if (sendMailView.ShowDialog()== DialogResult.OK)
   {
      Mail mail = sendMailView.CurrentItem;
      mail.AttachmentFiles.Add(ExportReportToPDF("Invoice.pdf"));
      mail.DeleteFilesAfterSend = true;
      mail.RequireAutentication = true;
      mail.Send();
   }
   sendMailView.Dispose();
}

在此示例中,senMailView.CurrentItem是邮件类的实例。我们只需要调用Send methis即可完成工作。

这是我在SO中写过的最大答案...我希望它可以帮到你:D如果你有任何问题,请给我打电话。顺便说一下,我对自己的英语并不感到自豪,所以如果文本有任何错误,请原谅我。