修改报告服务呈现的pdf,然后再将其发送到客户端

时间:2011-02-02 21:45:11

标签: reporting-services rendering

我想在报告服务报告的每个页面上添加一个包含合法身份信息和图形的PDF文件。此报告由Dynamics CRM的报告查看器呈现。我正在研究编写一个渲染扩展,它调用现有的PDF导出渲染扩展,并使用像ABCPdf这样的PDF组件。

我知道如何完成PDF后台渲染,但我无法从新实现中调用现有的渲染扩展。

现有的PDF呈现扩展是一个密封类,似乎无法使用其他实现的render方法。

然后我尝试使用http请求直接调用报表服务器,由于模拟问题,我无法使其工作。我收到以下错误消息:"没有包含指定域名和用户ID的Microsoft Dynamics CRM用户"

我认为我走在正确的轨道上,但我不知道如何从渲染扩展的上下文中获取安全凭证。

如果我只能将pdf的内容作为流来获取,我将能够为其添加背景。

public class PdfWithBackgroundRenderer : IRenderingExtension
    { 


        public void GetRenderingResource(Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStreamCallback, System.Collections.Specialized.NameValueCollection deviceInfo)
        {

        }

        public bool Render(Report report, System.Collections.Specialized.NameValueCollection reportServerParameters, System.Collections.Specialized.NameValueCollection deviceInfo, System.Collections.Specialized.NameValueCollection clientCapabilities, ref System.Collections.Hashtable renderProperties, Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStream)
        {
            //http://localhost/Reserved.ReportViewerWebControl.axd?ReportSession=3i414gm5fcpwm355u1ek0e3g&ControlID=417ac5edf4914b7a8e22cf8d4c7a3a8d&Culture=1043&UICulture=1033&ReportStack=1&OpType=Export&FileName=%7bF64F053A-5C28-E011-A676-000C2981D884%7d&ContentDisposition=OnlyHtmlInline&Format=PDF
            string Url = "http://localhost/Reserved.ReportViewerWebControl.axd";
            Url += "?ExecutionID=" + reportServerParameters["SessionID"];
            Url += "&ControlID=" + Guid.Empty;
            Url += "&Culture=1043";
            Url += "&UICulture=1033";
            Url += "&ReportStack=1";
            Url += "&OpType=Export";
            Url += "&FileName=" + report.Name;
            Url += "&ContentDisposition=OnlyHtmlInline";
            Url += "&Format=PDF";            

            Stream outputStream = createAndRegisterStream(report.Name, "pdf", Encoding.UTF8, "application/pdf", true, Microsoft.ReportingServices.Interfaces.StreamOper.CreateAndRegister);
            StreamWriter writer = new StreamWriter(outputStream);            
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Credentials = System.Net.CredentialCache.DefaultCredentials;            

            request.Timeout = 20000;
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

            StreamReader reader = new StreamReader(response.GetResponseStream());
            writer.Write(reader.ReadToEnd());      
            writer.Flush();

            return false;
        }

        public bool RenderStream(string streamName, Report report, System.Collections.Specialized.NameValueCollection reportServerParameters, System.Collections.Specialized.NameValueCollection deviceInfo, System.Collections.Specialized.NameValueCollection clientCapabilities, ref System.Collections.Hashtable renderProperties, Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStream)
        {
            return false;
        }

        public string LocalizedName
        {
            get { return "PDF Renderer with background"; }
        }

        public void SetConfiguration(string configuration)
        {

        }
    }

1 个答案:

答案 0 :(得分:1)

有一种方法,它只需要几行。 我们的想法是从新的渲染扩展中调用现有的渲染扩展的渲染方法。这将为您提供可以修改的流的渲染结果。

我无法在网上找到解决方案,但发现一些论坛答案声称无法完成。

困难的部分是了解所使用的委托功能。一旦了解了正在发生的事情,解决方案就变得简单了。

此代码使用Reporting Services 2008进行测试。如果要修改现有SSRS呈现扩展创建的呈现结果,此方法非常有用。您可以进行字符串替换,根据需要更改CSV输出,或者在我们的案例中签名或更新PDF文档。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.ReportingServices.OnDemandReportRendering;
using Microsoft.ReportingServices.Rendering.ImageRenderer;
using System.Globalization;
using System.IO;
using System.Net;

namespace ReportRendering.PDF
{

    public class PdfWithBackgroundRenderer : IRenderingExtension
    {
        //Add the existing rendering extension to the new class
        //In this case PDfRenderer from the ImageRenderer namespace
        private PDFRenderer pdfRenderer;

        //Stream to which the intermediate report will be rendered
        private Stream intermediateStream;
        private string _name;
        private string _extension;
        private Encoding _encoding;
        private string _mimeType;
        private bool _willSeek;
        private Microsoft.ReportingServices.Interfaces.StreamOper _operation;

        //Inititate the existing renderer in the constructor
        public PdfWithBackgroundRenderer()
            : base()
        {
            pdfRenderer = new PDFRenderer();
        }


        public void GetRenderingResource(Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStreamCallback, 
            System.Collections.Specialized.NameValueCollection deviceInfo)
        {

        }

        //New implementation of the CreateAndRegisterStream method
        public Stream IntermediateCreateAndRegisterStream(string name, string extension, Encoding encoding, string mimeType, bool willSeek, Microsoft.ReportingServices.Interfaces.StreamOper operation)
        {
            _name = name;
            _encoding = encoding;
            _extension = extension;
            _mimeType = mimeType;
            _operation = operation;
            _willSeek = willSeek;
            intermediateStream = new MemoryStream();
            return intermediateStream;
        }

        public bool Render(Report report, 
            System.Collections.Specialized.NameValueCollection reportServerParameters, 
            System.Collections.Specialized.NameValueCollection deviceInfo, 
            System.Collections.Specialized.NameValueCollection clientCapabilities, 
            ref System.Collections.Hashtable renderProperties, 
            Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStream)
        {

            //Call the render method of the intermediate rendering extension
            pdfRenderer.Render(report, reportServerParameters, deviceInfo, clientCapabilities, ref renderProperties, new Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream(IntermediateCreateAndRegisterStream));

            //Register stream for new rendering extension
            Stream outputStream = createAndRegisterStream(_name, _extension, _encoding, _mimeType, _willSeek, _operation);


            intermediateStream.Position = 0;

            //put stream update code here

            //Copy the stream to the outout stream
            byte[] buffer = new byte[32768];

            while (true) { 
                int read = intermediateStream.Read(buffer, 0, buffer.Length); 
                if (read <= 0) break; 
                outputStream.Write(buffer, 0, read); 
            }

            intermediateStream.Close();

            return false;
        }

        public bool RenderStream(string streamName, Report report, System.Collections.Specialized.NameValueCollection reportServerParameters, System.Collections.Specialized.NameValueCollection deviceInfo, System.Collections.Specialized.NameValueCollection clientCapabilities, ref System.Collections.Hashtable renderProperties, Microsoft.ReportingServices.Interfaces.CreateAndRegisterStream createAndRegisterStream)
        {
            return false;
        }

        public string LocalizedName
        {
            get { return "PDF Renderer with background"; }
        }

        public void SetConfiguration(string configuration)
        {
            pdfRenderer.SetConfiguration(configuration);
        }


    }
}