Received a undesired demand, Reporting service or the RDLC report can be made into Excel, PDF and other file format, for the general Muggle-type users, PDF read, Excel can be modified, the business unit wants to be in the report of the newspaper to divide; in other words, If you can print a PDF with Excel, you can do it as a result of whether the report is read or not, and there is no way to modify the possible results. (Let's not modify the PDF file or copy Excel into a PDF-like scenario)
I think of a way to add a floating watermark to a PDF file. In the same report, Word, Excel, and PDF files are consistent, and when the PDF file is added to the watermark, it is sufficient to form a compartment. In the PDF file plus floating watermark is not difficult, with Itextsharp can be done, but the exchange of PDF files of the Wenwen ReportViewer internal work, do not allow outsiders to intervene, in the exchange of PDF files, the foot needs a bit of hacking, good one to let the program Demon Hot Blood Boiling totem of the challenge!
The first step in analyzing the problem is to first analyze the principle of Reportviwer's PDF file:
When you perform a PDF exchange, it is actually called ReportViewer Httphandler,web.config to see the settings:
<add path= "Reserved.ReportViewerWebControl.axd" verb= "*" type= "Microsoft.Reporting.WebForms.HttpHandler, Microsoft.ReportViewer.WebForms, version=11.0.0.0, Culture=neutral, publickeytoken=89845dcd8080cc91 "validate=" False "/>
When you press the button on the Web, the browser is directed to a specific URL, which is transferred to the Opmode=export, Format=pdf, and returned by HttpHandler to the PDF file of the watch. If you want to move your foot in this process, There is a correct cut-in point is through the Global.asax or HttpModule suspend intercept beginrequest event, when the call to Reserved.ReportViewerWebControl.axd file to add a custom logically edit, modify the files to be transferred back content. But ReportViewer's HttpHandler was immediately written into the Httprepsonse and returned to the client after the PDF file, so that we could not intervene, so the next challenge was how to suspend intercept and modify its contents.
At this time, ASP. NET's another easy-to-use system: Response.filter, which allows us to write to our own stream object before HttpResponse writes the result byte[], can be modified and then transferred to the client's destination, as well.
typography shows pure text
Using System;
Using System.Collections.Generic;
Using System.IO;
Using System.Linq;
Using System.Text;
Using System.Web;
Class Expfilefilterstream:memorystream
{
Null
func<null;
Null
False
Public Expfilefilterstream (HttpResponse resp, func<byte[]> modifier)
{
Response = resp;
Output = resp. Filter;
This.modifier = modifier;
}
void Write (int count)
{
Since the ReportViewer will close the bufferoutput and divide it into a multi-segment flush back to the front end,
To re-activate the buffer function (due to the need to get the file full content),
But the first flush () is omitted, whereby the following logically is avoided for the first time partly flush ()
Note: The size of the ReportViewer in the segment flush is 81920, when less than this value means that you do not need to skip the flush
if (!response. BufferOutput && count = = 81920)
{
True
True
}
Base. Write (buffer, offset, count);
}
void Flush ()
{
if (Firstflush)
{
False
Return
}
Flush, will be sent back to the contents of the byte[] to the external logically edit and then retrieve
Base. ToArray ();
Null
Buff = modifier (buff);
Output. Write (buff, 0, buff. Length);
}
}
I wrote a simple filter stream object, the principle of which is to collect the files ReportViewer HttpHandler to be sent back in write (), and when Flush () returns the results, the previously received PDF file (byte[]) By external logically album, func<byte[], byte[]>, add a floating watermark to handle, and then return the modified version of the file to the real outputstream.
There are a few tricks: ReportViewer HttpHandler to reduce memory consumption and improve the efficiency of the response, will response.bufferoutput set to false, so that the exchange of files into a multi-segment flush () to pass back (each paragraph not over 81920 bytes). Since we need to receive the full file in order to modify and return it once, it is not possible to pass back some of the unmodified content in the first case. When write () changes the response.bufferoutput back to True, you can secretly cancel the multipart pass, and only then the first segment of Flush () is offing, so use a Firstflush flag to avoid the first flush (). Since Response.bufferoutput has been set to true, it will wait until all of the PDF files have been written into the write () to call Flush (), which is what MemoryStream saved is the full PDF file.
In the BeginRequest event, Response.filter's work was written as a httpmodule. The program is simple, more time is through the itextsharp in the upper left of the PDF printed on the PDF yyyy/mm/dd HH:mm:ss-like translucent floating watermark, Itext history, powerful features, the network is not difficult to find the example, very easy to complete.
typography shows pure text
Using System;
Using System.Collections.Generic;
Using System.Diagnostics;
Using System.Linq;
Using System.Text;
Using System.Web;
Using ITextSharp.text.pdf;
Using IText = Itextsharp.text;
Using Itextsharp.text;
Using System.IO;
Namespace Reportviewerhacking
{
Class Watermarkmodule:ihttpmodule
{
#region IHttpModule Members
void Dispose ()
{
}
void Init (HttpApplication context)
{
Context. BeginRequest + = Context_beginrequest;
}
void Context_beginrequest (object sender, EventArgs e)
{
As HttpApplication;
String url = App. CONTEXT.REQUEST.RAWURL;
var context = App. Context;
if (URL. Contains ("Reserved.ReportViewerWebControl.axd"))
{
var req = context. Request;
var resp = context. Response;
String opType = req["OpType"];
String name = req["name"];
string format = req["format"];
"PDF")
{
True
New Expfilefilterstream (RESP, (buff) =
{
Enter PDF content, plus floating watermark
New Pdfreader (Buff);
Itext.rectangle dimension = pr. GetPageSize (1);
New MemoryStream ();
New Pdfstamper (PR, MS);
Ref:http://bit.ly/10qirzk
Basefont BF =
FALSE);
New Itext.font (BF, 6, IText.Font.NORMAL, basecolor.black);
Pdfcontentbyte cb = stmp. Getovercontent (1);
Set Translucent Text
New Pdfgstate ();
Gstate. fillopacity = 0.2f;
Gstate. strokeopacity = 0.2f;
Cb. Setgstate (gstate);
Cb. Begintext ();
Cb. Setfontandsize (BF, 6);
Cb. Setcolorfill (Basecolor.black);
Cb. Showtextaligned (Pdfcontentbyte.align_left,
String. Format ("PDF {0:yyyy-mm-dd HH:mm:ss}", DateTime.Now),
Dimension. GetLeft (1), dimension. GetTop (5), 0);
Cb. Endtext ();
Stmp. Close ();
pr. Close ();
Return Ms. ToArray ();
});
}
}
}
#endregion
}
}
Will HttpModule hang into the ASP, and then as long as the ReportViewer to the PDF file, would be secretly added floating watermark, let me a little when hackers guest addiction, ha!!
[Go] Add a watermark to the PDF document exported by ReportViewer