1、背景
在项目需求中需要将角色信息打印出来,转化成pdf,常规的方法,前端就可以实现,但是当一个用户信息有几百条,几千条时怎么办?前端转化pdf依靠的是浏览器和电脑的性能,这时候就需要我们后台来处理了。
2、Itext
iText是著名的开放项目,是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。
。。。。。。。。
不多说了直接怼代码
生成一个pdf的流程
没多大用,看看熟悉熟悉生成过程,相当于io流那一套操作。
3、集成springboot
先做一个模板
先用word创建一个word文件
然后转换成pdf模板,然后将模板放到static静态文件包下,模板如下:
(1)、创建springboot项目
(2)、在pom.xml文件中添加如下依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.3</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
(3)、实体类
/**
* 专业素养竞赛成绩
*/
@Entity
@Table(name = "bt_user_pro_compt")
@Data
public class UserProCompt implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", insertable = false, nullable = false)
private Long id;
/**
* 用户ID
*/
@Column(name = "user_id", nullable = false)
private String userId;
/**
* 等级
0 无
1 A
2 B
3 C
*/
@Column(name = "degree", nullable = false)
private Integer degree;
@Column(name = "attachments", nullable = false)
private String attachments;
}
(4)、DO层操作
package com.zhitu.posreview.repository;
import com.zhitu.posreview.entity.UserOtoc;
import com.zhitu.posreview.entity.UserProCompt;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import java.util.List;
public interface UserProComptRepository extends JpaRepository<UserProCompt, Long>, JpaSpecificationExecutor<UserProCompt> {
List<UserProCompt> findAllByUserId(String userId);
}
(5)、service层
package com.zhitu.posreview.service;
import com.zhitu.posreview.entity.user.UserMessageList;
import javax.servlet.http.HttpServletResponse;
/**
* ProhectName posreview
* Description TODD
* Author zhengchaorui
* Data 2019/5/21 21:26
* Version 1.0
**/
public interface PdfService {
/**
* description:生成pdf(用户信息集成在一块)
* param:
* return
*/
void generatePDFFileTwo(String userId,HttpServletResponse response) throws Exception;
}
实现类
@Override
public void generatePDFFileTwo(String userId, HttpServletResponse response) throws Exception {
if (userId == null && "".equals(userId)) {
throw new PosreviewException(ResponseResultEnum.OPERATION_ERROR);
}
//pdf模板相对路径
String pdfModelPath = PathUtils.getPDFModelPath();
//pdf临时文件相对路径
String pdfTempPath = PathUtils.getPDFTempPath();
//pdf合并文件相对路径
String pdfExportPath = PathUtils.getPDFExportPath();
UserMessageList userMessageList = getUserMessageList(userId);
List<String> stringAllList = new ArrayList<>();
//循环遍历文件夹下的文件
List<String> dirlist = PdfUtils.findDir(pdfModelPath + "");
for (int a = 0; a < dirlist.size(); a++) {
String path = dirlist.get(a);
File file = new File(path);
String fileName = file.getName();
if (("专业素养竞赛成绩.pdf").equals(fileName)) {
List<UserProCompt> userProComptList = userMessageList.getUserProComptList();
if (userProComptList.size() != 0) {
String textFromPage = PdfUtils.readPdf(path);
for (UserProCompt proCompt : userProComptList) {
List<String> stringList = new ArrayList<>();
UserProCompt userProCompt = proCompt;
String s = userProCompt.toString();
Map<String, String> keyvalMaps = PdfUtils.ProcessField(s);
String degree = keyvalMaps.get("degree");
if (degree.equals("null")){
degree="0";
}
String degree1 = UserAttainmentLevelEnum.analysisString(Integer.valueOf(degree));
String tmpPage = textFromPage;
String strDegree = tmpPage.replaceAll("degree", degree1);
stringList.add(strDegree);
stringAllList.addAll(stringList);
}
}
}
(6)封装的工具类
package com.zhitu.posreview.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.zhitu.posreview.entity.bean.AttachmentData;
import com.zhitu.posreview.enums.user.UserTiptopEnum;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ResourceUtils;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @ProjectName: posreview
* @Package: com.zhitu.posreview.utils
* @ClassName: PathUtils
* @Author: zhengchaorui
* @Description: 相对路径解析工具类
* @Date: 2019/5/13 15:46
* @Version: 1.0.0
*/
@Slf4j
public class PathUtils {
public static String getRootPath() {
//获取跟目录
File file;
String path = null;
try {
file = new File(ResourceUtils.getURL("classpath:").getPath());
if(!file.exists()) {
file = new File("");
}
path = file.getAbsolutePath();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
return path;
}
public static String getTempPath() {
String rootPath = getRootPath();
//如果上传目录为/static/temp/,则可以如下获取:
File file = new File(rootPath,"static/temp/");
if(!file.exists()) {
boolean mkdirs = file.mkdirs();
}
return file.getAbsolutePath();
}
public static String getModelPath() {
String rootPath = getRootPath();
//如果上传目录为/static/model/,则可以如下获取:
File file = new File(rootPath,"static/model/");
if(!file.exists()) {
boolean mkdirs = file.mkdirs();
}
return file.getAbsolutePath();
}
public static String getExportPath() {
String rootPath = getRootPath();
//如果上传目录为/static/export/,则可以如下获取:
File file = new File(rootPath,"static/export/");
if(!file.exists()) {
file.mkdirs();
}
return file.getAbsolutePath();
}
public static String getPDFTempPath() {
String rootPath = getRootPath();
//如果上传目录为/static/temp/,则可以如下获取:
File file = new File(rootPath,"static/pdf/temp/");
if(!file.exists()) {
boolean mkdirs = file.mkdirs();
}
return file.getAbsolutePath();
}
public static String getPDFModelPath() {
String rootPath = getRootPath();
//如果上传目录为/static/model/,则可以如下获取:
File file = new File(rootPath,"static/pdf/model/");
if(!file.exists()) {
boolean mkdirs = file.mkdirs();
}
return file.getAbsolutePath();
}
public static String getPDFExportPath() {
String rootPath = getRootPath();
//如果上传目录为/static/export/,则可以如下获取:
File file = new File(rootPath,"static/pdf/export/");
if(!file.exists()) {
file.mkdirs();
}
return file.getAbsolutePath();
}
}
package com.zhitu.posreview.utils;
import com.itextpdf.text.Document;
import com.itextpdf.text.pdf.PdfCopy;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.parser.PdfTextExtractor;
import org.apache.commons.lang3.StringUtils;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.util.PDFMergerUtility;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* ProhectName posreview
* Description pdf工具类
* Author zhengchaorui
* Data 2019/5/21 21:58
* Version 1.0
**/
public class PdfUtils {
/**
* description 读取pdf文件,输出pdf模板
* param:
* return
*/
public static String readPdf(String path) {
String textFromPage = "";
PdfReader reader = null;
try {
reader = new PdfReader(path);
reader.getNumberOfPages();
/* 模板对象 */
textFromPage = PdfTextExtractor.getTextFromPage(reader, 1);
} catch (IOException e) {
e.printStackTrace();
}
return textFromPage;
}
/**
* description: 处理返回值
* param:
* return
*/
public static Map<String, String> ProcessField(String toString) {
String s1 = StringUtils.substringAfter(toString, "(");
String s2 = StringUtils.substringBefore(s1, ")");
Map<String, String> keyvalMaps = new HashMap<>();
String[] split = s2.split(", ");
for (String split1 : split) {
String[] split2 = split1.split("=");
if (split2.length == 2) {
keyvalMaps.put(split2[0], split2[1]);
}
}
return keyvalMaps;
}
/**
* description 循环遍历文件夹下的文件
* param:
* return
*
* @return
*/
public static List<String> findDir(String path) {
File dir = new File(path);
File[] fileList = dir.listFiles();
List<String> strList = new ArrayList<String>();
for (File f : fileList) {
if ((f.isFile())) {
strList.add(f.getAbsolutePath());
}
}
return strList;
}
//暂时不用
public static boolean mergePdfFiles(String[] files, String newfile) throws Exception {
boolean retValue = false;
Document document = null;
try {
document = new Document(new PdfReader(files[0]).getPageSize(1));
PdfCopy copy = new PdfCopy(document, new FileOutputStream(newfile));
document.open();
for (int i = 0; i < files.length; i++) {
PdfReader reader = new PdfReader(files[i]);
int n = reader.getNumberOfPages();
for (int j = 1; j <= n; j++) {
document.newPage();
PdfImportedPage page = copy.getImportedPage(reader, j);
copy.addPage(page);
}
}
retValue = true;
document.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
}
return retValue;
}
private static String[] getFiles(String folder) throws IOException {
File _folder = new File(folder);
String[] filesInFolder;
if(_folder.isDirectory()){
filesInFolder = _folder.list();
return filesInFolder;
} else {
throw new IOException("Path is not a directory");
}
}
/**
* description: 多个pdf合成一个pdf
* param:
* return
*/
public static void mergePdf(String filePath,String savePath) throws IOException, COSVisitorException {
//pdf合并工具
PDFMergerUtility mergePdf = new PDFMergerUtility();
String destinationFileName = "message.pdf";
String[] filesInFolder = getFiles(filePath);
for(int i = 0; i < filesInFolder.length; i++){
//循环添加要合并的pdf存放的路径
mergePdf.addSource(filePath + File.separator + filesInFolder[i]);
}
mergePdf.setDestinationFileName(savePath+ File.separator + destinationFileName);
//合并pdf
mergePdf.mergeDocuments();
}
/**
* description:创建文件
* param:
* return
*/
public static File createFile(File file){
if(!file.exists()) {
file = new File("");
}
return file;
}
/**
* description 删除文件
* param:
* return
*/
public static void delFile(String filePath) {
File file = new File(filePath);
if (file.exists() && file.isFile()) {
file.delete();
}
}
/**
* description 弹出文件
* param:
* return
*/
public static void writerResponse(String fileName ,HttpServletResponse response, String exportPath) {
try {
response.setHeader("Content-Disposition", "attachment;filename="+ java.net.URLEncoder.encode(fileName, "UTF-8")+".pdf");
response.setContentType("application/octet-stream");
FileInputStream fis = new FileInputStream(exportPath);
byte[] content = new byte[fis.available()];
fis.read(content);
fis.close();
ServletOutputStream sos = response.getOutputStream();
sos.write(content);
sos.flush();
sos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void getReflect(Object model) throws Exception{
for (Field field : model.getClass().getDeclaredFields()) {
field.setAccessible(true);
Map<String, Object> map = new HashMap<>();
map.put(field.getName(),field.get(model));
}
}
}
(7)、接口controller
package com.zhitu.posreview.controller;
import com.zhitu.posreview.vo.GetPage;
import com.zhitu.posreview.result.ResponseResult;
import com.zhitu.posreview.service.PdfService;
import com.zhitu.posreview.utils.ResponseResultUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletResponse;
/**
* ProhectName posreview
* Description 下载pdf功能
* Author zhengchaorui
* Data 2019/5/20 18:08
* Version 1.0
**/
@RestController
@CrossOrigin
@RequestMapping("/pdf")
public class PdfController {
@Autowired
private PdfService pdfService;
@GetMapping("/makePdfFile")
public void pdfFile(@RequestParam("id") String userId, HttpServletResponse response) throws Exception{
pdfService.generatePDFFileTwo(userId,response);
}
}
以上使用的技术springboot+JPA+mysql+iText