网上有很多关于PDF导出的文章,但是个人感觉实现的过于复杂,又是模板又是html的,有的还需要字体模板的支持,本片文章只是实现简单的PDF表格导出,可以实现PDF动态表格导出/预览,这类文章网上很少,就给你们整理一篇吧!
实现思路:本地创建PDF文件 --》打开PDF文件 --〉写入各种数据 --》保存PDF --〉 将PDF输出到页面下载 --》 删除本地PDF文件
第一步:导入相关的依赖,如果原来有依赖记得替换一下哦,免得版本不一致导致其他产生的各种问题。
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.5</version> </dependency> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itext-asian</artifactId> <version>5.2.0</version> </dependency>
第二步:创建所需要的实体类
package com.hyper.pdf;
import lombok.Data;
/**
* 标题名称/内容设置实体类
*/
@Data
public class ProcessVo {
/**
* 序号
*/
private String index;
/**
* 审核人
*/
private String assignee;
/**
* 审核人名称
*/
private String assigneeName;
/**
* 审核时间
*/
private String verifyTime;
/**
* 审核结果
*/
private String verifyResult;
/**
* 审核意见
*/
private String verifyMessage;
}
package com.hyper.pdf;
import lombok.Data;
import java.util.List;
@Data
public class ProcessTaskVo {
private String taskName="审核人";
private String startUserName="审核发起人";
private String startTime="2022-03-04";
/**
* 导出的数据 processVoList
*/
private List<ProcessVo> processVoList;
}
第三步:所有代码我都放到了控制层里面,各位自行开发细化,按照自己的要求调整即可。
package com.hyper.web;
import cn.hutool.core.bean.BeanUtil;
import com.amazonaws.util.IOUtils;
import com.hyper.pdf.ProcessTaskVo;
import com.hyper.pdf.ProcessVo;
import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@RestController
@RequestMapping("/pdf")
public class HelloController {
@GetMapping("/pdf")
public void processPdfSample(HttpServletRequest request, HttpServletResponse response) {
ProcessTaskVo processTaskVo = new ProcessTaskVo();
// 扩大指针作用域
Document document = null;
ByteArrayOutputStream fileOut = new ByteArrayOutputStream();
OutputStream responseOutputStream = null;
try {
// 导出PDF文件名称
final String pdfDocName = "周报" + ".pdf";
// 系统路径
File file = new File(pdfDocName);
file.createNewFile();
//1:建立Document对象实例
document = new Document();
StringBuilder filename = new StringBuilder();
//PDF标题
String pdfName = "测试导出的PDF";
filename.append(pdfName).append(new SimpleDateFormat("yyyyMMddHHmm").format(new
Date()));
document.addAuthor("Author@SALES");
document.addCreationDate();
document.addCreator("Creator@SALES");
document.setMargins(10, 10, 10, 10);
PdfWriter pdfWriter = PdfWriter.getInstance(document, fileOut);
pdfWriter.setPdfVersion(PdfWriter.VERSION_1_4);
// 3:打开文档
document.open();
//解决中文不显示问题
BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
Font fontChina14 = new Font(bfChinese, 14);
Font fontChina12 = new Font(bfChinese, 12);
// 4:向文档添加内容
Paragraph titleParagraph = new Paragraph(pdfName, fontChina14);
// 居中
titleParagraph.setAlignment(Element.ALIGN_CENTER);
document.add(titleParagraph);
// 空格
Paragraph blank1 = new Paragraph(" ");
document.add(blank1);
// 表格处理及查询数据
java.util.List<ProcessVo> processVoLists = new ArrayList<>();
for (int i = 0; i < 30; i++) {
ProcessVo processVo1 = new ProcessVo();
processVo1.setIndex(i+"");
processVo1.setAssignee("李四");
processVo1.setAssigneeName("张三");
processVo1.setVerifyTime("2022-03-04");
processVo1.setVerifyResult("通过");
processVoLists.add(processVo1);
}
processTaskVo.setProcessVoList(processVoLists);
PdfPTable table = packageTable(processTaskVo, fontChina12);
if (null != table) {
document.add(table);
}
// 5:关闭文档
document.close();
//注释可在线预览
witerFile(request, response, file, false);
responseOutputStream = response.getOutputStream();
fileOut.writeTo(responseOutputStream);
responseOutputStream.close();
//删除文件
file.delete();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (DocumentException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
fileOut.close();
responseOutputStream.close();
} catch (IOException exception) {
System.out.printf("下载异常");
}
}
}
/**
* 写出文件
*
* @param request
* @param response
* @param file
* @param deleteOnExit
*/
private void witerFile(HttpServletRequest request, HttpServletResponse response, File file, boolean deleteOnExit) {
response.setCharacterEncoding(request.getCharacterEncoding());
response.setContentType("application/pdf");
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
//这里主要防止下载的PDF文件名乱码
String fileName = URLEncoder.encode(file.getName(), "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
IOUtils.copy(fis, response.getOutputStream());
response.flushBuffer();
} catch (Exception e) {
System.out.printf("下载异常111");
} finally {
if (fis != null) {
try {
fis.close();
if (deleteOnExit) {
file.deleteOnExit();
}
} catch (IOException e) {
System.out.printf("下载异常222");
}
}
}
}
public static PdfPTable packageTable(ProcessTaskVo processTaskVo, Font fontZH) {
try {
// 创建table下面通过table.addCell添加的时候必须添加整行内容的所有列
PdfPTable table = new PdfPTable(6);
table.setWidthPercentage(100.0F);
//第一行是列表名
table.setHeaderRows(1);
table.getDefaultCell().setHorizontalAlignment(1);
java.util.List<ProcessVo> processVoList = processTaskVo.getProcessVoList();
if (null != processVoList && processVoList.size() > 0) {
List<ProcessVo> newProcessVoList = new ArrayList<>();
ProcessVo processVo = new ProcessVo();
processVo.setIndex("数据1");
processVo.setAssignee("审批人2");
processVo.setAssigneeName("审批人姓名3");
processVo.setVerifyTime("审批时间");
processVo.setVerifyResult("审批结果");
processVo.setVerifyMessage("审批意见");
newProcessVoList.add(processVo);
for (ProcessVo tableProcessVo : processVoList) {
ProcessVo newProcessVo = new ProcessVo();
BeanUtil.copyProperties(tableProcessVo, newProcessVo);
newProcessVoList.add(newProcessVo);
}
//遍历List 获取每一列的数据,填充到pdfTable中
newProcessVoList.forEach(vo -> {
table.addCell(createCell(vo.getIndex(), fontZH));
table.addCell(createCell(vo.getAssignee(), fontZH));
table.addCell(createCell(vo.getAssigneeName(), fontZH));
table.addCell(createCell(vo.getVerifyTime(), fontZH));
table.addCell(createCell(vo.getVerifyResult(), fontZH));
table.addCell(createCell(vo.getVerifyMessage(), fontZH));
});
}
//cell跨页
table.setKeepTogether(false);
table.setSplitLate(false);
table.setSplitRows(true);
return table;
} catch (Exception e) {
return null;
}
}
private static PdfPCell createCell(String value, Font fontZH) {
PdfPCell cell = new PdfPCell();
cell.setPhrase(new Phrase(value, fontZH));
cell.setColspan(1);
cell.setUseAscender(true);
cell.setUseDescender(true);
//水平居中
cell.setHorizontalAlignment(Element.ALIGN_CENTER);
//垂直居中
cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
return cell;
}
}
最后实现的效果如下,可以实现预览后下载的,具体的话看代码备注,上面代码应该是全的,如果发现有漏掉的代码或者依赖可以留言作者,定会第一时间完善的。