java 将html 转换成pdf 的方法

 时间:2024-10-21 14:37:49

1、薪姚蟪食引子当我们写一个web程序时,经常会遇到将某个特定页面的内容导出成报告的功能。本文将实现利用Java 8,Spring Boot, Wkhtmltopdf, Thymeleaf将HTML页面导出成PDF文本。2.总纲在我们实现具体功能前,我们先看看创建一个PDF文档的过程大约分三步走:a) 浏览器(服务端)发送一个HTTP请求到我们的后台程序,并说明HTML页面的url和所创建的PDF文档的文件名;b) 写Java后台代码调用并 wkhtmltopdf 命令行工具以读取HTML文档并将其转为PDF文档;c) Java后台程序读取转好的PDF文档,并将其返回到到浏览器端。在开始前我们之先,先安装wkhtmltopdf3.技术实现1. 安装Wkhtmltopdf首先我们需要安装wkhtmltopdf命令行工具。我们可以去其官网选择对应的操作系统版本下载并安装(本文作者安装的是windows-64bit版本)官网下载地址:https://wkhtmltopdf.org/downloads.html如果你用的是 macOS 可以利用Homebrew进行wkhtmltopdf的安装。只要输入如下命令行即可完成安装:brew install Caskroom/cask/wkhtmltopdf2. 配置环境变量我的Wkhtmltopdf是默认安装路径’C:\ProgramFiles\wkhtmltopdf’计算机-属性-高级系统设置-环境变量-系统变量-Path添加wkhtmltopdf的路径,如下图所示:配置完Path后我们就可以去写Java代码啦。开发环境与工具:a) Spring Boot 1.4.3 REALEASEb) Thymeleafc) Maven 3.3d) Eclipse oxygen3. 项目最终结构4. 项目依赖 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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.thinkingingis</groupId> <artifactId>spring-boot-htmltopdf</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-htmltopdf</name> <url>http://maven.apache.org</url> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.3.RELEASE</version> </parent> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build></project>5. 从HTML页面创建PDF文档5.1 Model层在我们具体实现HTML转PDF功能之前,我们需要创建一个类用于存放wkhtmltopdf所需要的参数信息。我们创建PdfFileRequest .java 类,包含两个属性 filename 属性是我们所创建PDF文档的文件名 sourceHtmlUrl 属性是HTML文档的URL地址PdfFileRequest .javapackage org.thinkingingis.model;public class PdfFileRequest { private String fileName; private String sourceHtmlUrl; public String getFileName() { return fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public String getSourceHtmlUrl() { return sourceHtmlUrl; } public void setSourceHtmlUrl(String sourceHtmlUrl) { this.sourceHtmlUrl = sourceHtmlUrl; }}5.2 Service层PdfFileCreator.javapackage org.thinkingingis.service;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.StringWriter;import java.util.Arrays;import java.util.List;import java.util.concurrent.TimeUnit;import javax.servlet.http.HttpServletResponse;import org.apache.tomcat.util.http.fileupload.IOUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.stereotype.Service;import org.thinkingingis.model.PdfFileRequest;@Servicepublic class PdfFileCreator { private static final Logger LOGGER = LoggerFactory.getLogger(PdfFileCreator.class); public void writePdfToResponse(PdfFileRequest fileRequest, HttpServletResponse response) { String pdfFileName = fileRequest.getFileName(); requireNotNull(pdfFileName, "The file name of the created PDF must be set"); requireNotEmpty(pdfFileName, "File name of the created PDF cannot be empty"); String sourceHtmlUrl = fileRequest.getSourceHtmlUrl(); requireNotNull(sourceHtmlUrl, "Source HTML url must be set"); requireNotEmpty(sourceHtmlUrl, "Source HTML url cannot be empty"); List<String> pdfCommand = Arrays.asList( "wkhtmltopdf", sourceHtmlUrl, "-" ); ProcessBuilder pb = new ProcessBuilder(pdfCommand); Process pdfProcess; try { pdfProcess = pb.start(); try(InputStream in = pdfProcess.getInputStream()) { writeCreatedPdfFileToResponse(in, response); waitForProcessBeforeContinueCurrentThread(pdfProcess); requireSuccessfulExitStatus(pdfProcess); setResponseHeaders(response, fileRequest); } catch (Exception ex) { writeErrorMessageToLog(ex, pdfProcess); throw new RuntimeException("PDF generation failed"); } finally { pdfProcess.destroy(); } } catch (IOException ex) { throw new RuntimeException("PDF generation failed"); } } private void requireNotNull(String value, String message) { if (value == null) { throw new IllegalArgumentException(message); } } private void requireNotEmpty(String value, String message) { if (value.isEmpty()) { throw new IllegalArgumentException(message); } } private void writeCreatedPdfFileToResponse(InputStream in, HttpServletResponse response) throws IOException { OutputStream out = response.getOutputStream(); IOUtils.copy(in, out); out.flush(); } private void waitForProcessBeforeContinueCurrentThread(Process process) { try { process.waitFor(2, TimeUnit.SECONDS); } catch (InterruptedException ex) { Thread.currentThread().interrupt(); } } private void requireSuccessfulExitStatus(Process process) { if (process.exitValue() != 0) { throw new RuntimeException("PDF generation failed"); } } private void setResponseHeaders(HttpServletResponse response, PdfFileRequest fileRequest) { response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileRequest.getFileName() + "\""); } private void writeErrorMessageToLog(Exception ex, Process pdfProcess) throws IOException { LOGGER.error("Could not create PDF because an exception was thrown: ", ex); LOGGER.error("The exit value of PDF process is: {}", pdfProcess.exitValue()); String errorMessage = getErrorMessageFromProcess(pdfProcess); LOGGER.error("PDF process ended with error message: {}", errorMessage); } private String getErrorMessageFromProcess(Process pdfProcess) { try { BufferedReader reader = new BufferedReader(new InputStreamReader(pdfProcess.getErrorStream())); StringWriter writer = new StringWriter(); String line; while ((line = reader.readLine()) != null) { writer.append(line); } return writer.toString(); } catch (IOException ex) { LOGGER.error("Could not extract error message from process because an exception was thrown", ex); return ""; } }}5.3 REST API实现PdfController.javapackage org.thinkingingis.controller;import javax.servlet.http.HttpServletResponse;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.RequestBody;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.bind.annotation.RestController;import org.thinkingingis.model.PdfFileRequest;import org.thinkingingis.service.PdfFileCreator;@RestControllerpublic class PdfController { private final PdfFileCreator pdfFileCreator; @Autowired public PdfController(PdfFileCreator pdfFileCreator) { this.pdfFileCreator = pdfFileCreator; } @RequestMapping(value = "/api/pdf", method = RequestMethod.POST) public void createPdf(@RequestBody PdfFileRequest fileRequest, HttpServletResponse response) { pdfFileCreator.writePdfToResponse(fileRequest, response); } }5.4 Controller层PrintPdfController.javapackage org.thinkingingis.controller;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import javax.servlet.http.HttpServletResponse;import org.apache.tomcat.util.http.fileupload.IOUtils;import org.springframework.boot.web.client.RestTemplateBuilder;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import org.springframework.web.client.RestTemplate;import org.thinkingingis.model.PdfFileRequest;@Controller@RequestMapping("/print")public class PrintPdfController { private final RestTemplate restTemplate; public PrintPdfController(RestTemplateBuilder restTemplateBuilder) { this.restTemplate = restTemplateBuilder.build(); } @RequestMapping(value = "/pdf", method = RequestMethod.GET) public void createPdfFromUrl(HttpServletResponse response) { PdfFileRequest fileRequest = new PdfFileRequest(); fileRequest.setFileName("index.pdf"); fileRequest.setSourceHtmlUrl("http://blog.csdn.net/gisboygogogo/article/"); byte[] pdfFile = restTemplate.postForObject("http://localhost:8080/api/pdf", fileRequest, byte[].class ); writePdfFileToResponse(pdfFile, "index.pdf", response); } private void writePdfFileToResponse(byte[] pdfFile, String fileName, HttpServletResponse response) { try (InputStream in = new ByteArrayInputStream(pdfFile)) { OutputStream out = response.getOutputStream(); IOUtils.copy(in, out); out.flush(); response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\""); } catch (IOException ex) { throw new RuntimeException("Error occurred when creating PDF file", ex); } }}6. 启动项目输入 http://localhost:8080/index点击 ‘打印’ 就会将 ‘http://blog.csdn.net/gisboygogogo/article/’ 页面转成PDF文档,保存即可。

热门搜索
文明伴我行手抄报内容 小学消防安全手抄报 团结友爱手抄报图片 趣味语文手抄报 法制校园手抄报 数学手抄报大全 小学生教师节手抄报 安全逃生手抄报 法制在我身边手抄报 绿色校园手抄报资料