65.9K
CodeProject 正在变化。 阅读更多。
Home

将 LocalReport 作为 PDF 附件发送电子邮件

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.76/5 (13投票s)

2007年9月20日

5分钟阅读

viewsIcon

64714

使用 LocalReport 和 ReportDataSources,将 PDF 作为附件流式传输到电子邮件中

引言

如果您正在应用程序中使用 ReportViewer 或 ReportingServices,并且曾经对自己说过:“您知道,如果我能将此报表作为电子邮件附件发送给某人,那将是多么棒的一件事”,那么您来对地方了。在我上一个项目中,我们正在使用 ReportViewer,并有很多报表闲置着,我发现自己也这样说。我不想将 PDF 文件写入服务器的文件系统,然后将其附加到电子邮件,然后再清理我留下的痕迹。我想直接将其流式传输到电子邮件中。以下是我完成这项任务的方法。

背景

本文假定您已将网站设置为使用 ASP.NET 2.0 的标准 SMTP 设置。您的 web.config 应具有类似以下的节:

<!-- SMTP Settings -->
    <system.net>
        <mailSettings>
            <smtp deliveryMethod="Network" from="no-reply@mywebsite.com">
                <network host="localhost" port="25" defaultCredentials="true"/>
            </smtp>
        </mailSettings>
    </system.net>

本文将假定您还拥有一个可用的报表及其关联的数据源。本文的范围不包括解释报表的创建或使用报表查看器。有很多关于这方面的教程。本文将专注于在内存中创建报表并将其作为附件流式传输到电子邮件中。

Using the Code

确保您在代码中拥有所有需要的命名空间。我们将使用以下命名空间:

  • System.Net.Mail
  • Microsoft.Reporting.WebForms
  • System.IO

因此,为了开始将报表设置为附件,您必须做的第一件事就是正确设置报表及其数据源。

LocalReport lr = new LocalReport();
lr.ReportPath = HttpContext.Current.Server.MapPath("~/Reports/myReport.rdlc");

上面的代码在内存中创建了一个新的 LocalReport,并将其路径设置为实际报表定义本地客户端 (.rdlc) 文件。过程中的下一步是设置报表的数据源。我们通过使用表适配器并将其添加到本地报表的数据源集合中来完成此操作。在此示例中,我们将假定我们的报表中包含两个数据源,也许还有一个子报表显示出来。

MyFirstDataSetTableAdapters.MyFirstTableAdapter ta1 = 
        new MyFirstDataSetTableAdapters.MyFirstTableAdapter();
MySecondDataSetTableAdapters.MySecondTableAdapter ta2 = 
        new MySecondDataSetTableAdapters.MySecondTableAdapter();

ReportDataSource ds1 = new ReportDataSource
    ("MyFirstDataSet_MyFirstTableAdapter", ta1.GetData(myParam1, myParam2));
ReportDataSource ds2 = new ReportDataSource
    ("MySecondDataSet_MySecondTableAdapter", ta2.GetData(myParam3));

您可以看到,在上面的代码中,我们创建了表适配器 ta1ta2。然后,我们使用表适配器的 GetData 方法作为 dataSourceValue 创建了两个 ReportDataSource 实例。我们可能需要像这里一样向表适配器方法传递几个参数 - 这完全取决于您的架构。在这里,我们仅通过向 GetData 方法传递几个伪参数来展示其外观。

这里的关键部分是确保数据源的名称与报表中的名称完全相同。您可以通过查看报表设计器中的数据源来获取此信息,然后基本上进行复制和粘贴。如果名称不正确,报表将根本不会生成。

然后,通过调用 Add 方法并传入相应的变量 ,我们将每个 ReportDataSource 添加到 LocalReport 数据源集合中。

lr.DataSources.Add(ds1);
lr.DataSources.Add(ds2); 

因此,从这一点开始,我们应该有一个 LocalReport,其中包含两个映射到我们数据集中的表的两个数据源,一切都准备就绪。下一步将是设置电子邮件附件。为此,我们需要将 LocalReport 渲染到一个流中,以便我们可以将其用作电子邮件附件。第一步是设置 LocalReportRender 方法所需的所有变量,然后将报表渲染到内存中。

Warning[] warnings;
string[] streamids;
string mimeType;
string encoding;
string extension;

byte[] bytes = lr.Render("PDF", null, out mimeType, 
        out encoding, out extension, out streamids, out warnings);

您在这里可以看到,我们将报表格式设置为 PDF。如果我们愿意,我们也可以使用 Excel 或其他有效的输出类型。我们还为 deviceInfo 参数发送了 null。如果您愿意,可以发送一个包含格式正确的 XML 设备信息的字符串。其余参数如您所见是输出参数。对于此应用程序,我们不使用任何这些参数。执行此代码后,我们现在将在内存中拥有一个 localReport,它存储为字节字符串。我们现在准备将这些字节作为附件流式传输到我们的电子邮件中。

MemoryStream s = new MemoryStream(bytes);
s.Seek(0, SeekOrigin.Begin); 

我们在这里从字节字符串创建一个 MemoryStream,并通过查找将其位置设置到流的开头。如果我们不查找流的开头,那么当我们在创建附件时,我们将位于流的末尾,附件中将不会添加任何内容。

Attachment a = new Attachment(s, "myReport.pdf"); 

我们创建一个新的电子邮件 Attachment,并将我们的 MemoryStream(即我们通过执行 LocalReportRender 方法获得的字节字符串)以及附件的名称传递进去。现在,我们可以创建一封电子邮件,添加我们的附件,并将报表发送给幸运的收件人。

MailMessage message = new MailMessage(
    "my_friend@herEmail.com", "me@myEmail.com", 
    "A report for you!", "Here is a report for you");
message.Attachments.Add(a);
SmtpClient client = new SmtpClient();
client.Send(message);

首先,我们创建邮件消息,并添加发件人、收件人、主题和正文字符串参数。然后,通过执行 Add 方法并以内存流作为参数,将附件添加到邮件的附件集合中。然后,我们获取一个新的 SmtpClient 并发送邮件。

关注点

通过这种方式将报表创建为流并将其附加到电子邮件中的好处是,所有操作都在内存中完成。无需进行文件创建和清理工作。您为 ReportViewer 创建的任何报表也可以在这里使用。

历史

  • 2007 年 9 月 20 日 - 第一次修订
© . All rights reserved.