views:

162

answers:

3

I have a website that has a bunch of PDFs that are pre-created and sitting on the webserver.

I don't want to allow a user to just type in a URL and get the PDF file (ie http://MySite/MyPDFFolder/MyPDF.pdf)

I want to only allow them to be viewed when I load them and display them.

I have done something similar before. I used PDFSharp to create a PDF in memory and then load it to a page like this:

protected void Page_Load(object sender, EventArgs e)
{
    try 
    {
        MemoryStream streamDoc = BarcodeReport.GetPDFReport(ID, false);
        // Set the ContentType to pdf, add a header for the length
        // and write the contents of the memorystream to the response
        Response.ContentType = "application/pdf";
        Response.AddHeader("content-length", Convert.ToString(streamDoc.Length));
        Response.BinaryWrite(streamDoc.ToArray());
        //End the response
        Response.End();
        streamDoc.Close();
    }
    catch (NullReferenceException)
    {
        Communication.Logout();
    }


}

I tried to use this code to read from a file, but could not figure out how to get a MemoryStream to read in a file.

I also need a way to say that the "/MyPDFFolder" path is non-browsable.

Thanks for any suggestions

+5  A: 

To load a PDF file from the disk into a buffer:

byte [] buffer;
using(FileStream fileStream = new FileStream(Filename, FileMode.Open))
{
    using (BinaryReader reader = new BinaryReader(fileStream))
    {
         buffer = reader.ReadBytes((int)reader.BaseStream.Length);
    }
}

Then you can create your MemoryStream like this:

using (MemoryStream msReader = new MemoryStream(buffer, false))
{
     // your code here.
}

But if you already have your data in memory, you don't need the MemoryStream. Instead do this:

    Response.ContentType = "application/pdf";
    Response.AddHeader("Content-Length", buffer.Length.ToString());
    Response.BinaryWrite(buffer);
    //End the response
    Response.End();
    streamDoc.Close();
Keltex
Thanks for the example code.
Vaccano
If you want to prevent direct access (User, Other Web site links or Search Engine Based) I would use the above method but then wrap it in a handler (ashx). Then you could verify the source of the request and server it out accordingly.
jaredmroberts
+1  A: 

Anything that is displayed on the user's screen can be captured. You might protect your source files by using a browser-based PDF viewer, but you can't prevent the user from taking snapshots of the data.

As far as keeping the source files safe...if you simply store them in a directory that is not under your web root...that should do the trick. Or you can use an .htaccess file to restrict access to the directory.

sangretu
I am fine if they save, screen shot or what ever after they view it. Some pdfs should not be viewed by some users. that is what I am trying to prevent. I will look tha tthe .htaccess file.
Vaccano
A: 

Keltex's code works for limiting who can get to the file. If the user isn't authorized for a particular file, give them a page with an error message, otherwise use that code to relay them the PDF. The URL then won't be directly to a PDF, but rather a script, so that will give you 100% control over who is permitted to access it.

Rather than putting the PDFs in question in an accessible location and messing with the configuration to hide them, you could put them someplace in the server that isn't directly web accessible. Since you'll have code reading the file into a buffer and relaying it to the user anyway, it doesn't matter where on the server the file is located, so long as it is accessible to your code.

matthock