get the PDF from a URL and push it to the clients browser for download

Dravidian picture Dravidian · Nov 6, 2014 · Viewed 9k times · Source

I have PDFs mounted on an external server. I have to access them in my Java servlet and push them to the clients browser. The PDF should get downloaded directly or it may open a 'SAVE or OPEN' dialog window. This is what i am trying in my code but it could not do much.

URL url = new URL("http://www01/manuals/zseries.pdf");
ByteArrayOutputStream bais = new ByteArrayOutputStream();
InputStream in = url.openStream();

int FILE_CHUNK_SIZE = 1024 * 4;
byte[] chunk = new byte[FILE_CHUNK_SIZE]; 
int n =0;
 while ( (n = in.read(chunk)) != -1 ) {
        bais.write(chunk, 0, n);
  }

I have tried many ways to do this but could not succeed. I welcome if you have any good method to do this!

Answer

RealSkeptic picture RealSkeptic · Nov 6, 2014

When you read the data, you get it inside your program memory, which is on the server side. To get it to the user's browser, you have to also write everything that you have read.

Before you start writing, though, you should give some appropriate headers.

  • Indicate that you are sending over a PDF file, by setting the mime type
  • Set the content length.
  • Indicate that the file is intended for download rather than showing inside the browser.

To set the mime type, use

response.setContentType("application/pdf");

To set the content length, assuming it's the same content length that you get from the URL, use:

HttpURLConnection connection = (HttpURLConnection)url.openConnection();
connection.connect();
if ( connection.getResponseCode() == 200 ) {
    int contentLength = connection.getContentLength();
    response.setContentLength( contentLength );

To indicate that you want the file to be downloaded, use:

    response.setHeader( "Content-Disposition", "attachment; filename=\"zseries.pdf\"";

(Take care to change the file name to whatever you want the user to see in the save dialog box)

Finally, get the input stream from the URLConnection you just opened, get the servlet's response output stream, and start reading from one and writing to the other:

    InputStream pdfSource = connection.getInputStream();
    OutputStream pdfTarget = response.getOutputStream();

    int FILE_CHUNK_SIZE = 1024 * 4;
    byte[] chunk = new byte[FILE_CHUNK_SIZE]; 
    int n =0;
    while ( (n = pdfSource.read(chunk)) != -1 ) {
        pdfTarget.write(chunk, 0, n);
    }
} // End of if

Remember to use try/catch around this, because most of these methods throw IOException, timeout exceptions etc., and to finally close both streams. Also remember to do something meaningful (like give an error output) in case the response was not 200.