Mishal Harish Mishal Harish - 7 months ago 42
Java Question

How can I serve a PDF to a browser without storing a file on the server side?

I have two methods. One that generates a PDF at the server side and another that downloads the PDF at the client side.

How can i do this without storing it in the Server side and allow the client side to directly download this.

The Following are the two methods:

public void downloadPDF(HttpServletRequest request, HttpServletResponse response) throws IOException{

response.setContentType("application/pdf");
response.setHeader("Content-disposition","attachment;filename="+ "testPDF.pdf");
FileInputStream fis = null;
DataOutputStream os = null;

try {
File f = new File("C://New folder//itext3.pdf");
response.setHeader("Content-Length",String.valueOf(f.length()));

fis = new FileInputStream(f);
os = new DataOutputStream(response.getOutputStream());
byte[] buffer = new byte[1024];
int len = 0;
while ((len = fis.read(buffer)) >= 0) {
os.write(buffer, 0, len);
}

} catch (Exception e) {
e.printStackTrace();
} finally {
fis.close();
os.flush();
os.close();
}
response.setHeader("X-Frame-Options", "SAMEORIGIN");
}


And:

public Document generatePDF() {

Document doc = new Document();
try {
File file = new File("C://New folder//itext_Test2.pdf");
FileOutputStream pdfFileout = new FileOutputStream(file);
PdfWriter.getInstance(doc, pdfFileout);

doc.addAuthor("TestABC");
doc.addTitle("Aircraft Details");
doc.open();


Anchor anchor = new Anchor("Aircraft Report");
anchor.setName("Aircraft Report");

Chapter catPart = new Chapter(new Paragraph(anchor), 1);

Paragraph para1 = new Paragraph();
Section subCatPart = catPart.addSection(para1);
para1.add("This is paragraph 1");

Paragraph para2 = new Paragraph();
para2.add("This is paragraph 2");


doc.add(catPart);

doc.close();


} catch (Exception e) {
e.printStackTrace();
}
return doc;
}

Answer

The people who advise you to use response.getOutputStream() instead of creating a FileOutputStream are right. See for instance the Hello Servlet from Chapter 9 of my book:

public class Hello extends HttpServlet {
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        response.setContentType("application/pdf");
        try {
            // step 1
            Document document = new Document();
            // step 2
            PdfWriter.getInstance(document, response.getOutputStream());
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph("Hello World"));
            document.add(new Paragraph(new Date().toString()));
            // step 5
            document.close();
        } catch (DocumentException de) {
            throw new IOException(de.getMessage());
        }
    }
}

However, some browsers experience problems when you send bytes directly like this. It's safer to create the file in memory using a ByteArrayOutputStream and to tell the browser how many bytes it can expect in the content header:

public class PdfServlet extends HttpServlet {

    protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
        try {
            // Get the text that will be added to the PDF
            String text = request.getParameter("text");
            if (text == null || text.trim().length() == 0) {
                 text = "You didn't enter any text.";
            }
            // step 1
            Document document = new Document();
            // step 2
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PdfWriter.getInstance(document, baos);
            // step 3
            document.open();
            // step 4
            document.add(new Paragraph(String.format(
                "You have submitted the following text using the %s method:",
                request.getMethod())));
            document.add(new Paragraph(text));
            // step 5
            document.close();

            // setting some response headers
            response.setHeader("Expires", "0");
            response.setHeader("Cache-Control",
                "must-revalidate, post-check=0, pre-check=0");
            response.setHeader("Pragma", "public");
            // setting the content type
            response.setContentType("application/pdf");
            // the contentlength
            response.setContentLength(baos.size());
            // write ByteArrayOutputStream to the ServletOutputStream
            OutputStream os = response.getOutputStream();
            baos.writeTo(os);
            os.flush();
            os.close();
        }
        catch(DocumentException e) {
            throw new IOException(e.getMessage());
        }
    }
}

For the full source code, see PdfServlet. You can try the code here: http://demo.itextsupport.com/book/