1.添加Maven依赖
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
2.工具类
package com.dzqc.dz.common.util;
import com.itextpdf.text.pdf.BaseFont;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
public class PdfUtils {
/**
* 把URL转换为PDF
* @return
* @throws Exception
*/
public static boolean htmlToPdf2(String outputFile, String url)
throws Exception {
File outFile = new File(outputFile);
if (!outFile.exists()) {
outFile.getParentFile().mkdirs();
}
OutputStream os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(url);
String fontPath="/simsun.ttc";
// 解决中文支持问题
ITextFontResolver fontResolver = renderer.getFontResolver();
fontResolver.addFont(fontPath, BaseFont.IDENTITY_H,BaseFont.NOT_EMBEDDED);
renderer.layout();
renderer.createPDF(os);
os.flush();
os.close();
System.out.println("文件转换成功");
return true;
}
}
3.Controller层
/**
* 批量导出座次表
*
* @param roomId
* @return
*/
@RequestMapping("/exportSeatNumPlanPDF")
@ResponseBody
public MyAjaxResult exportSeatNumPlanPDF(String roomId,String subjectId, HttpServletRequest request, HttpServletResponse response) {
String path1 = System.getProperty("root") + File.separator + "resources" + File.separator + "PDF" + File.separator;
File file = new File(path1);
if (!file.exists() && !file.isDirectory()) {
System.out.println("//不存在");
file.mkdir();
}
if (subjectId==null||"".equals(subjectId)) {
return MyAjaxResult.fail_300("考试科目id不能为空");
}
BufferedOutputStream out = null;
BufferedInputStream in = null;
String[] split = null;
if (null != roomId && !"".equals(roomId)) {
split = roomId.split(",");
}
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");//设置日期格式
String format = df.format(new Date());
String ip = SystemConstants.get("ip");
SystemConstants.get("ip");
String port = SystemConstants.get("port");
try {
System.out.println(roomId);
boolean b = PdfUtils.htmlToPdf2(path1 + format+"-座次表.pdf", "http://"+ip+":" + port + request.getContextPath() + "/stuexamroom/selectRoomDoorPDF?path=zdbpzcb&roomId=" + roomId+"&subjectId="+subjectId);
System.err.println(b);
if (b) {
File f = new File(path1 + format+"-座次表.pdf");
out = new BufferedOutputStream(response.getOutputStream());
in = new BufferedInputStream(new FileInputStream(f));
response.setContentType(new MimetypesFileTypeMap().getContentType(f));// 设置response内容的类型
String filename = format+"-座次表";
if (isMSBrowsers.isMSBrowser(request)) {
filename = URLEncoder.encode(filename, "UTF-8");
} else {
filename = new String(filename.getBytes("utf-8"), "ISO8859-1");
}
response.setHeader("Content-disposition", "attachment;filename=" + filename + "." + "pdf");// 设置头部信息
byte[] buffer = new byte[1024];
int length = 0;
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
out.flush();
}
} catch (Exception e) {
e.printStackTrace();
return MyAjaxResult.fail_500("网络异常");
} finally {
try {
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return MyAjaxResult.success("下载成功");
}
@RequestMapping("/selectRoomDoorPDF")
public ModelAndView selectRoomDoorPDF(String path, String roomId,String subjectId) {
String[] split = null;
if (!"".equals(roomId)&& !"null".equals(roomId)) {
split = roomId.split(",");
}
List<Examroom> stuExamRoom = null;
try {
stuExamRoom = stuExamRoomService.selectRoomDoorPDF(split,subjectId);
System.out.println(stuExamRoom);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Map<String, Object> ma = new HashMap<>(16);
ma.put("stuExamRooms", stuExamRoom);
return new ModelAndView("pages/dzBackEnd/" + path, ma);
}
4.页面
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8" isELIgnored="false" %>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<html>
<head>
<meta charset="UTF-8"></meta>
<meta name="viewport" content="width=device-width, initial-scale=1.0"></meta>
<meta http-equiv="X-UA-Compatible" content="ie=edge"></meta>
<title>座次表</title>
<style>
@page {
size: A4;
margin: 0;
}
html, body {
margin: 0;
padding: 0;
}
h2, h4 {
text-align: center;
}
.wrap {
width: 794px;
/* height: 1123px; */
height: auto;
margin: 0 auto;
}
ul {
width: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
li {
list-style: none;
width: 20%;
height: auto;
float: left;
margin-bottom: 3px;
text-align: center;
}
li img {
width: 120px;
}
li p {
margin: 0;
text-align: center;
}
</style>
</head>
<body bgcolor='white' style='font-family:SimSun; height:100%;' screen_capture_injected='true' ryt11773='1'>
<c:set var="length" scope="session" value="${fn:length(stuExamRooms)}"/>
<c:forEach items="${stuExamRooms}" var="room" varStatus="i">
<c:set var="roompage" scope="session" value="${fn:length(room.stuSubjectRooms)}"/>
<h4> 第${room.roomCode}考场 (个数:${roompage})</h4>
<div class="wrap">
<ul>
<c:forEach items="${room.stuSubjectRooms}" var="var" varStatus="q">
<li>
<img src="${path}/resources/photo/${var.ksh}.jpg"></img>
<p>${var.seatNum} ${var.name}</p>
</li>
<c:set var="count" scope="session" value="${q.count%35}"/>
<c:if test="${count==0}">
<p style="page-break-after:always;"></p>
</c:if>
</c:forEach>
</ul>
</div>
<c:if test="${length!=i.count}">
<p style="page-break-after:always;"></p>
</c:if>
</c:forEach>
<%--<h4> 第${rooCode}考场 (个数:${fn:length(list)})</h4>
<div class="wrap">
<ul>
<c:forEach items="${list}" var="var" varStatus="q">
<li>
<img src="${path}/resource/img/dz/mg_photo.jpg"></img>
<p>${var.sear} ${var.name}</p>
</li>
<c:set var="count" scope="session" value="${q.count%35}"/>
<c:if test="${count==0}">
<p style="page-break-after:always;"></p>
</c:if>
</c:forEach>
</ul>
</div>--%>
</body>
</html>
5.效果
6.注意点
1.div的文字换行
在生成的pdf中,默认不会换行;实现换行在div的style中加入 word-wrap:break-word;
<div style="width:100px;height:200px; word-wrap:break-word;">
2.在转换pdf的时候对html文件的格式要求比较严格,标签必需有结束标签,否则将会报一系列错误
例如:换行只有一个<br>标签
则会报异常:
ERROR: '元素类型 "br" 必须由匹配的结束标记 "</br>" 终止。'
如果是<br></br>则不会报异常。