tags:

views:

828

answers:

6

I have a URL to a PDF and I want to serve up the PDF to my page viewer.

I can successfully (I think) retrieve the PDF file. Then when I do the Response.BinaryWrite() I get a "The file is damaged and could not be repaired" error from the adobe reader.

Here's the code I have:

protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            byte[] output = DoWork("Http://localhost/test.pdf");
            Response.Clear();
            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition", "inline; filename=MyPDF.PDF");
            Response.AddHeader("content-length", output.Length.ToString());
            Response.BinaryWrite(output);
            Response.End();
        }
    }

    public byte[] DoWork(string requestUrl)
    {
        byte[] responseData;
        HttpWebRequest req = null;
        HttpWebResponse resp = null;
        StreamReader strmReader = null;

        try
        {
            req = (HttpWebRequest)WebRequest.Create(requestUrl);

            using (resp = (HttpWebResponse)req.GetResponse())
            {
                byte[] buffer = new byte[resp.ContentLength];
                BinaryReader reader = new BinaryReader(resp.GetResponseStream());
                reader.Read(buffer, 0, buffer.Length);
                responseData = buffer;
            }
        }
        finally
        {
            if (req != null)
            {
                req = null;
            }

            if (resp != null)
            {
                resp.Close();
                resp = null;
            }
        }

        return responseData;

    }
A: 

Try to flush the response after the binary write...

Response.BinaryWrite(output);
Response.Flush();
Response.End();

Alternatively, instead of inline, try to output the PDF as an attachment:

Response.AddHeader("Content-Disposition", "attachment;filename=MyPDF.PDF");
sduplooy
Flush is not a method on BinaryReader
Rick Kierner
Replaced it with Close according to MSDN: Flushing the stream will not flush its underlying encoder unless you explicitly call Flush or Close.
sduplooy
flushing a reader?? what somehow doesn't make much sense... :) You read until it's empty, don't you?
roe
+1  A: 

Try saving the resulting file to your disk. Then open the file with a text editor. Maybe there are some errors in your script/source file.

bouke
good sanity check!
Dead account
This led me to the answer
Rick Kierner
+2  A: 

Apparently, I need to use ReadBytes() For some reason, when reading a PDF from a URL, You don't get all of the bytes that you requested.

    protected void Page_Load(object sender, EventArgs e)
    {
        if (IsPostBack)
        {
            byte[] output = DoWork("Http://localhost/test.pdf");
            Response.Clear();
            Response.ContentType = "application/pdf";
            Response.AddHeader("content-disposition", "attachment");
            Response.AddHeader("content-length", output.Length.ToString());
            Response.BinaryWrite(output);
            Response.End();
        }
    }

    public byte[] DoWork(string requestUrl)
    {
        byte[] responseData;
        HttpWebRequest req = null;
        HttpWebResponse resp = null;
        StreamReader strmReader = null;

        try
        {
            req = (HttpWebRequest)WebRequest.Create(requestUrl);

            using (resp = (HttpWebResponse)req.GetResponse())
            {
                byte[] buffer = new byte[resp.ContentLength];
                using (BinaryReader reader = new BinaryReader(resp.GetResponseStream()))
                {
                    buffer = reader.ReadBytes(buffer.Length);
                    reader.Close();
                }
                responseData = buffer;
            }
        }
        finally
        {
            if (req != null)
            {
                req = null;
            }

            if (resp != null)
            {
                resp.Close();
                resp = null;
            }
        }

        return responseData;

    }
Rick Kierner
A: 

When I did this in Perl the other day (as a quick hack for our intranet), the crux of the script was:

binmode(STDOUT);
print "Content-type: application/pdf\n\n";
binmode(FILE);
print <FILE>;
close(FILE);

The key points being to make sure that the input and output streams are in binary mode, i.e. as you've found, the PDF needs to be interpreted as binary data throughout the chain.

Nick
A: 

You might be able to simplify your code quite a bit by using the WebClient class

Here's the MSDN documentation. Its not as cumbersome as the lower level HttpWebRequest class.

AndrewDotHay
A: 

You can also try to use FileStream the read the file

 string strPath = Request.PhysicalApplicationPath 
                  + "\\document\\Test.pdf";
 FileStream fStream = new FileStream
            (strPath, FileMode.Open, FileAccess.Read);
 StreamReader sReader = new StreamReader(fStream);
Eduardo Molteni