The following article describes how you can create a proxy page that converts a
SQL Server Report into a PDF file. When the code is executed, it will make a call
to a report on a SQL Reporting Services Server, generate a PDF file and then present it to the user as an option download.
A nice benefit to this process is that you never have to save a physical file on the server and then direct the client to that file. Everything is done in memory, so there will be no file permission problems or disk space issues to deal with.
While this code is useful for creating PDF copies of an SRS report, the true value
is that you no longer have to grant everyone access to the reports within Reporting
Services. To do this, you simply log into the Reporting Services website and set
up a single user account that will have access to the reports. From there, be sure
to reference this same user account in the credentials when setting up the web request.
This code can also be easily modified to download other types of files from other
Using the Code
To begin, we must first construct a URI that points to the report on the report
string url = "http://localhost/ReportServer/Pages/ReportViewer.aspx?%2fInvoices%2fCurrent&rs%3aCommand=Render&rs%3AFormat=PDF&InvoiceId=1";
Breakdown of the above URL:
- This should point to the ReportViewer page that comes with reporting services.
/- This is a folder that you set up in Reporting Services. If your report is in a sub folder, you will need to specify the full path
separated by %2f
- This is the name of your report as seen in reporting services
- This is required to tell the server to generate the report
- This will render the output as PDF. Reporting Services can render in other formats as well
- This is a custom parameter that gets passed into the report. In this instance, we simply pass id #1
It is possible to create a custom filename for the PDF when it gets downloaded to the client.
string customFileName = "NewFileName.pdf";
This section shows how to set up user credentials to access the Report Server. I
CredentialCache.DefaultCredentials for testing on localhost. When
accessing this on a remote server, you may need to pass in user credentials.
WebRequest request = WebRequest.Create(url);
request.ContentType = @"application/pdf";
string userName = "";
string password = "";
string domain = "";
if (userName.Length > 0)
System.Net.NetworkCredential credentials = new NetworkCredential(userName, password, domain);
request.Credentials = credentials;
request.Credentials = CredentialCache.DefaultCredentials;
This code captures the response from the Report Server and then saves the results into
MemoryStream object so that it can be passed back to the client.
To accomplish this, we call the
ReadFully method to convert the
Stream into a byte array which then gets
fed into the
MemoryStream. Source code for this method can be found at http://www.developerfusion.co.uk/show/4696/ and is also included in the sample project.
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
using (Stream stream = response.GetResponseStream())
byte data = ReadFully(stream, response.ContentLength);
ms = new MemoryStream(data);
The code for ReadFully can be seen below. This was originally posted at http://www.developerfusion.co.uk/show/4696/
public static byte ReadFully(Stream stream, long initialLength)
if (initialLength < 1)
initialLength = 32768;
byte buffer = new byte[initialLength];
int read = 0;
while ((chunk = stream.Read(buffer, read, buffer.Length - read)) > 0)
read += chunk;
if (read == buffer.Length)
int nextByte = stream.ReadByte();
if (nextByte == -1)
byte newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[read] = (byte)nextByte;
buffer = newBuffer;
byte ret = new byte[read];
Array.Copy(buffer, ret, read);
The final block of code clears out the current
Response object and then
sends it to the client for download. We also add a header to declare a custom filename
and then set the content type to PDF so the browser knows how to handle the file.
The last line of code simply sends the
MemoryStream object to the browser
which then prompts the user for download.
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "inline; filename=" + customFileName);
Points of Interest
While this example shows how to download a PDF file from SRS, many more formats
are available such as CSV and Excel. To use these formats, locate the
Format=PDF command in the URI and change PDF to either CSV or Excel. You will also have to
This code uses SQL Reporting Services as an example, however it is not limited to
just SRS. You can easily change the URL and alter the content types to access any type of file on the web.