Spring MVC PDF Download
In this tutorial you will see how to create PDF and attach in response so that user can open or save generated PDF in his local system.
To generate report in other format please visit previous tutorial using below link:
Steps to generate PDF report:
- Sample maven SpringMVCDownloadPDF project:
- pom.xml:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.javahonk</groupId> <artifactId>SpringMVCDownloadXML</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>SpringMVCDownloadXML Maven Webapp</name> <url>http://maven.apache.org</url> <properties> <junit.version>3.8.1</junit.version> <SpringVersion>4.0.6.RELEASE</SpringVersion> <spring-jdbc.version>4.0.6.RELEASE</spring-jdbc.version> <json.version>20140107</json.version> <jackson.version>1.9.10</jackson.version> <log4j.version>1.2.16</log4j.version> <jtds.version>1.2</jtds.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit.version}</version> <scope>test</scope> </dependency> <!-- Spring dependencies --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${SpringVersion}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${SpringVersion}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${SpringVersion}</version> </dependency> <!-- Spring and Transactions --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-jdbc.version}</version> </dependency> <!-- Jackson JSON Mapper --> <dependency> <groupId>org.codehaus.jackson</groupId> <artifactId>jackson-mapper-asl</artifactId> <version>${jackson.version}</version> </dependency> <dependency> <groupId>org.json</groupId> <artifactId>json</artifactId> <version>${json.version}</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>${log4j.version}</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.0.6</version> </dependency> </dependencies> <build> <finalName>SpringMVCDownloadXML</finalName> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> <version>3.1</version> </plugin> </plugins> </build> </project>
- dispatcher-servlet.xml:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd"> <context:component-scan base-package="com.javahonk.controller" /> <mvc:annotation-driven/> </beans>
- web.xml:
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5"> <display-name>Archetype Created Web Application</display-name> <servlet> <servlet-name>dispatcher</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>dispatcher</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/dispatcher-servlet.xml</param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> </web-app>
- CreatePDF.java:
package com.javahonk.controller; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.text.SimpleDateFormat; import java.util.Date; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Phrase; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfWriter; public class CreatePDF { private static Font TIME_ROMAN = new Font(Font.FontFamily.TIMES_ROMAN, 18,Font.BOLD); private static Font TIME_ROMAN_SMALL = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD); /** * @param args */ public static Document createPDF(String file) { Document document = null; try { document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(file)); document.open(); addMetaData(document); addTitlePage(document); createTable(document); document.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (DocumentException e) { e.printStackTrace(); } return document; } private static void addMetaData(Document document) { document.addTitle("Generate PDF report"); document.addSubject("Generate PDF report"); document.addAuthor("Java Honk"); document.addCreator("Java Honk"); } private static void addTitlePage(Document document) throws DocumentException { Paragraph preface = new Paragraph(); creteEmptyLine(preface, 1); preface.add(new Paragraph("PDF Report", TIME_ROMAN)); creteEmptyLine(preface, 1); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("MM/dd/yyyy"); preface.add(new Paragraph("Report created on " + simpleDateFormat.format(new Date()), TIME_ROMAN_SMALL)); document.add(preface); } private static void creteEmptyLine(Paragraph paragraph, int number) { for (int i = 0; i < number; i++) { paragraph.add(new Paragraph(" ")); } } private static void createTable(Document document) throws DocumentException { Paragraph paragraph = new Paragraph(); creteEmptyLine(paragraph, 2); document.add(paragraph); PdfPTable table = new PdfPTable(3); PdfPCell c1 = new PdfPCell(new Phrase("First Name")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Last Name")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Test")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); table.setHeaderRows(1); for (int i = 0; i < 5; i++) { table.setWidthPercentage(100); table.getDefaultCell().setHorizontalAlignment(Element.ALIGN_CENTER); table.getDefaultCell().setVerticalAlignment(Element.ALIGN_MIDDLE); table.addCell("Java"); table.addCell("Honk"); table.addCell("Success"); } document.add(table); } }
- SpringMVCController.java
package com.javahonk.controller; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; @Controller public class SpringMVCController { @RequestMapping(value = "/downloadPDF") public void downloadPDF(HttpServletRequest request, HttpServletResponse response) throws IOException { final ServletContext servletContext = request.getSession().getServletContext(); final File tempDirectory = (File) servletContext.getAttribute("javax.servlet.context.tempdir"); final String temperotyFilePath = tempDirectory.getAbsolutePath(); String fileName = "JavaHonk.pdf"; response.setContentType("application/pdf"); response.setHeader("Content-disposition", "attachment; filename="+ fileName); try { CreatePDF.createPDF(temperotyFilePath+"\\"+fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); baos = convertPDFToByteArrayOutputStream(temperotyFilePath+"\\"+fileName); OutputStream os = response.getOutputStream(); baos.writeTo(os); os.flush(); } catch (Exception e1) { e1.printStackTrace(); } } private ByteArrayOutputStream convertPDFToByteArrayOutputStream(String fileName) { InputStream inputStream = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { inputStream = new FileInputStream(fileName); byte[] buffer = new byte[1024]; baos = new ByteArrayOutputStream(); int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return baos; } }
- index.jsp:
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> <%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> <title>Spring MVC PDF Download Example</title> </head> <body> <form:form action="downloadPDF" method="post" id="downloadPDF"> <h3>Spring MVC PDF Download Example</h3> <input id="submitId" type="submit" value="Downlaod PDF"> </form:form> </body> </html>
- For this demo I will run this project on tomcat server but you could use any server. Below is output:
- For more details of Spring MVC please visit its official site here
Download Project: SpringMVCDownloadPDF
I have used your pdf class into my projects. I am getting empty pdf document.
Any idea?
I have found some difference in HttpServletResponse. In your class HttpServletResponse type is ResponseFacade, but in my class it is HttpSessionSecurityContextRepository$SaveToSessionResponseWrapper.
OutputStream type is CoyoteOutputStream in your class, but in my class it is SaveContextOnUpdateOrErrorResponseWrapper$SaveContextServletOutputStream
Can you please help?
THANK YOU for the POST form idea, to get the file to DL – instead of window.open, iframe, yada yada.
Sorry it was my application problem and it is working fine
Thanks for this post…very short and sweet.
I am getting 404 resource not available.
URL : http://localhost:8080/SpringMVCDownloadPDF/index.jsp
jsp is there in WEB-INF/views
Please suggest.
Thanks a lot for the post, really helpful .. but I have two questions about the method:
1) since we use a temp file with the same name each time, if two request at the same time comes won’t one of them overwrite the other file (specially that in my app I have to do multiple operations like watermarking after creating the pdf), so the first user might get wrong data?
2) shouldn’t the files be deleted after being served (maybe after flush in a finally)?
Thx a lot for the tutorial, really helpful .. however; I have a question regarding concurrent requests, wouldn’t this make conflict specially if you are making different pdfs based on user request data? should we generate unique id for each request and use it as a temp name? also, shouldn’t we delete the file or it gets deleted automatically when the session is closed?
sorry for the repetition but I didn’t see my first comment so I thought there was an error? so I repeated the same questions .. sorry again