views:

66

answers:

3

I have yer typical servlet that streams a pdf to a browser. The pdfs are stored on an internal server from which my servlet fetches. If I hit the servlet directly from the browser, the pdf is displayed. If I try the same URL in an <IMG> tag in a web page, ... broken pipe.

Any insight on why this should be?

As an experiment, I can stream gifs without issue.

Here's the code which I pretty much scavenged from the innerwebs:

public class PdfServlet extends HttpServlet {

    private static final Logger log = Logger.getLogger(PdfServlet.class.getName());

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) {

        String url = (String) req.getParameter("url");

        log.info("The URL is " + url);
        String format = "application/pdf";
//           String format = "image/gif";

        streamBinaryData(url, format, res);

    }

    /*
     * This Method Handles streaming Binary data
     * <p>
     * @param String urlstr ex: http;//localhost/test.pdf etc.
     * @param String format ex: pdf or audio_wav or msdocuments etc.
     * @param ServletOutputStream outstr
     * @param HttpServletResponse resp
     */
    private void streamBinaryData(
            String urlstr,
            String format,
            HttpServletResponse resp) {

        ServletOutputStream outstr = null;
        String ErrorStr = null;

        try {
            outstr = resp.getOutputStream();

            //find the right MIME type and set it as contenttype
            resp.setContentType(format);
            BufferedInputStream bis = null;
            BufferedOutputStream bos = null;
            try {
                URL url = new URL(urlstr);
                URLConnection urlc = url.openConnection();
                int length = urlc.getContentLength();

                resp.setContentLength(length);
//                resp.setHeader("Content-Length", String.valueOf(+length));
//                resp.setHeader("Content-Disposition", "inline");

                // Use Buffered Stream for reading/writing.
                InputStream in = urlc.getInputStream();
                bis = new BufferedInputStream(in);
                bos = new BufferedOutputStream(outstr);
                byte[] buff = new byte[length];
                int bytesRead;
                // Simple read/write loop.
                while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                    log.info("Got a chunk of " + bytesRead);
                    bos.write(buff, 0, bytesRead);
                }
            } catch (Exception e) {
                e.printStackTrace();
                ErrorStr = "Error Streaming the Data";
                outstr.print(ErrorStr);
            } finally {
                log.info("finally!!!");
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
                if (outstr != null) {
                    outstr.flush();
                    outstr.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

...and the HTML file. The pdf fails with a broken pipe and the gif image is displayed even though the content type is being returned as 'application/pdf'.

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title>Cheesy Servlet Experiment</title>
    </head>
    <body>
        <h1>Cheesy Servlet Experiment</h1>

        <P>
            <img src="http://10.0.0.9/ServletExperiment/pdf?url=http%3a%2f%2fwww.samplepdf.com%2fsample.pdf" alt="yah mon">
        <P>
            <img src="http://10.0.0.9/ServletExperiment/pdf?url=http%3a%2f%2fbbs.homeshopmachinist.net%2fimages%2fstatusicon%2fforum_new.gif" alt="yah mon">
    </body>
</html>

Edit - the following works in FF. I don't know how standard it is.

<object data="http://www.samplepdf.com/sample.pdf" type="application/pdf" width="600" height="600">
    alt : <a href="http://www.samplepdf.com/sample.pdf"&gt;test.pdf&lt;/a&gt;
</object>

Interesting info here. Looks reasonably well supported.

+3  A: 

Can your browser even display PDF files in img elements? That's really unlikely. I think the browser ends the connection when it finds out that it's actually not an image.

Some browsers don't complain about content-types. They check the image file and figure out which format the image is in by itself. That can explain why your GIF image is displayed.

Emil Vikström
I never would have thought of that.
Tony Ennis
+1  A: 

you should use an anchor tag (if you have to use an img, have an A wrap the IMG with the IMG's src pointing to a real image). The href of the anchor will be your servelt that displays PDFs. make suer you set the right content-type in the servlet.

kartheek
Not quite what I had in mind, but it works.
Tony Ennis
+2  A: 

The problem is that you are trying to display a PDF document with the img Tag. img can handle only simple image formats like JPEG, GIF or PNG.

Usually the plain browser is not able to display PDF content on its own. If there is no PDF viewer plugin installed then the browser will only show a save dialog to download the PDF file.

So the safest way would be that your HTML page only contains a link to your PDF file. Maybe with a target="_blank" to open a new browser window.

vanje