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

Tags: servletserverByteArrayOutputStreamin memoryiText 5

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

public void generatePDF() throws Exception {
    Document doc = new Document();
    File file = new File("C://New folder//itext_Test.pdf");
    FileOutputStream pdfFileout = new FileOutputStream(file);
    PdfWriter.getInstance(doc, pdfFileout);
    doc.open();
    Paragraph para = new Paragraph("Test");
    doc.add(catPart);
    doc.close();
}
 
public void downloadPDF(HttpServletRequest request, HttpServletResponse response)
    throws IOException{
    response.setContentType("application/pdf");
    response.setHeader("Content-disposition","attachment;filename="+ "testPDF.pdf");
    try {
        File f = new File("C://New folder//itext_Test.pdf");
        FileInputStream fis = new FileInputStream(f);
        DataOutputStream os = new DataOutputStream(response.getOutputStream())
        response.setHeader("Content-Length",String.valueOf(f.length()));
        byte[] buffer = new byte[1024];
        int len = 0;
        while ((len = fis.read(buffer)) >= 0) {
            os.write(buffer, 0, len);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}
How can I serve the PDF file to the client without storing the file on the server side and allow the client side to directly download the file that is generated?

Posted on StackOverflow on May 26, 2015 by Mishal Harish

You to can use any OutputStream when creating a PDF file, so in theory, you could use a response.getOutputStream(). See for instance the Hello Servlet from Chapter 9 of "iText in Action - Second Edition":

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.