1、配置文件中引入itext7依赖jar包
jar包从git上可以获取不同版本https://github.com/itext/itext7/releases
7.1.11
com.itextpdf
kernel
${itext.version}
com.itextpdf
io
${itext.version}
com.itextpdf
layout
${itext.version}
com.itextpdf
forms
${itext.version}
com.itextpdf
pdfa
${itext.version}
com.itextpdf
pdftest
${itext.version}
com.itextpdf
font-asian
${itext.version}
2、代码部分
导出接口
@ApiOperation(value = "导出竞卖活动列表")
@RequestMapping(value = "/export/{encrypted}",method = {RequestMethod.GET})
public void getPdf(@PathVariable String encrypted, HttpServletResponse resp, HttpServletRequest req)
{
String decrypted = new String(Base64.getUrlDecoder().decode(encrypted.getBytes()));
AuctionListRequest listReq = JSON.parseObject(decrypted, AuctionListRequest.class);
//查询竞卖信息
List auctionVOList = getAuctions(listReq);
if(CollectionUtils.isEmpty(auctionVOList)){
throw new SbcRuntimeException();
}
try {
ServletOutputStream os = resp.getOutputStream();
String destDir = req.getServletContext().getRealPath("/")+ File.separator+"pdfFiles"+File.separator;
File destDirFile = new File(destDir);
if(!destDirFile.exists()){
destDirFile.mkdirs();
}
// PdfFont font = PdfFontFactory.createFont(FONT, PdfEncodings.IDENTITY_H,false);//解决显示中文字体
List files = new ArrayList<>();
auctionVOList.forEach(auctionVO->{
//文件名:商家名称-活动名称-活动开始/结束时间
String name = auctionVO.getSupplierName()+"-"+auctionVO.getAuctionName()+"-"+auctionVO.getStartTime().format(DateTimeFormatter.ofPattern(DateUtil.FMT_TIME_2))+"~"+auctionVO.getEndTime().format(DateTimeFormatter.ofPattern(DateUtil.FMT_TIME_2))+".pdf";
File file = new File(destDir,name);
PdfWriter writer = null;
PdfFont font = null;
try {
if(!file.exists()){
file.createNewFile();
}
writer = new PdfWriter(file);
font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H",true);
} catch (Exception e) {
log.error("/auction/export/params error: ", e);
throw new SbcRuntimeException(SiteResultCode.ERROR_000001);
}
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf).setFont(font).setFontSize(14);
//竞拍信息
document.add(new Paragraph("活动详情-"+auctionVO.getAuctionType().getDesc()).setTextAlignment(TextAlignment.CENTER));
Table auctionTable = PdfUtil.createTable(2);//创建表格
Field[] auctionFields = PdfAuctionDto.class.getDeclaredFields();//获取dto 对象中所有的属性
PdfUtil.generateNormalTable(auctionFields,generateAuctionMap(auctionVO),font,auctionTable);
document.add(auctionTable);
//拍品信息
Table auctionGoodsTable = PdfUtil.createTable(12);//创建表格
Field[] auctionGoodsFields = PdfAuctionGoodsDto.class.getDeclaredFields();//获取dto 对象中所有的属性
List
PDF工具类
package com.wanmi.sbc.auction.pdf;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.layout.Style;
import com.itextpdf.layout.borders.Border;
import com.itextpdf.layout.borders.DashedBorder;
import com.itextpdf.layout.element.Cell;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Table;
import com.itextpdf.layout.property.UnitValue;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
public class PdfUtil {
/**
* 创建没有边框的Cell --设置字体大小为8,内边距设置成0,边框设置为无边框
* @return
*/
public static Cell getCellNoBorder(){
return new Cell().setFontSize(10).setPaddings(0,0,0,0).setBorder(Border.NO_BORDER);//setBorder(Border.)
}
/**
* 获取上边框为虚线的cell--因为默认情况下,边框默认是黑色实线边框,这里要把上边框设置成虚线并设置字体
* @return
*/
public static Cell getCellDashedBorder(){
return new Cell().addStyle(new Style().setBorderTop(new DashedBorder(1))).setBorder(Border.NO_BORDER).setFontSize(10);
}
/**
* 创建两列的表格并插入图片
* @return
*/
public static Table createTable(int numColumns){
//创建两列的表格
//表格在pdf整个页面的宽度百分比,这个值越小,整个个pdf表格越小,越靠近左边(这样说可能不对,大家可以试下)
//设置外边距
//设置图片在第一行表格中,cell(1,2) 代表这一行,有两列合并成一列,图像设置成自适应。这里有一个问题,就是当图像设置成自适应的时候通过new Table(new float[]{4,6})——创建两列的表格,列长度就是每个数组长度 创建的表格就会出现表格列长度改变的问题。
return new Table(numColumns).
setWidth(UnitValue.createPercentValue(100)).
setMarginTop(10);
}
/**
* 排序并生成指定样式的表格
* @param a
* @param map
* @param font
* @param table
*/
public static void generateNormalTable(Field[] a, Map map, PdfFont font, Table table){
for (Field field : a) { //遍历模板字段
PdfValue annotation = field.getDeclaredAnnotation(PdfValue.class);//获取字段属性上的注释
if (0==annotation.typeFile()){
//如果是没有边框的Cell
table.addCell(getCellNoBorder().add(new Paragraph(annotation.colName()).setFont(font)));
//字体样式右对齐,默认是左对齐的
table.addCell(getCellNoBorder().add(new Paragraph(map.get(field.getName())==null?"-":map.get(field.getName()).toString())).setFont(font));
}
}
}
/**
* 有表头的Table
* @param a
* @param maps
* @param font
* @param table
*/
public static void generateHeadTable(Field[] a, List> maps, PdfFont font, Table table){
//表头
for (Field field : a) { //遍历模板字段
PdfValue annotation = field.getDeclaredAnnotation(PdfValue.class);//获取字段属性上的注释
table.addCell(new Paragraph(annotation.colName()).setFont(font).setFontSize(10));
}
//内容
maps.forEach(map->{
for (Field field : a) { //遍历模板字段
//字体样式右对齐,默认是左对齐的
table.addCell(new Paragraph(map.get(field.getName())==null?"-": map.get(field.getName()).toString())).setFont(font).setFontSize(10);
}
});
}
}
PDF字段实体,这边只放一个作为示例
package com.wanmi.sbc.auction.pdf;
import lombok.Data;
@Data
public class PdfAuctionDto {
/**
* 所属商家
*/
@PdfValue(colName = "所属商家:",typeFile = 0)
private String supplierName;
/**
* 审核人员
*/
@PdfValue(colName = "审核人员:",typeFile = 0)
private String auditPerson;
/**
* 审核状态
*/
@PdfValue(colName = "审核状态:",typeFile = 0)
private String auditStatus;
/**
* 审核时间
*/
@PdfValue(colName = "审核时间:",typeFile = 0)
private String auditTime;
/**
* 活动名称
*/
@PdfValue(colName = "活动名称:",typeFile = 0)
private String auctionName;
/**
* 竞卖类型
*/
@PdfValue(colName = "竞卖类型:",typeFile = 0)
private String auctionType;
/**
* 起止时间
*/
@PdfValue(colName = "起止时间:",typeFile = 0)
private String auctionTime;
/**
* 延时周期
*/
@PdfValue(colName = "延时周期:",typeFile = 0)
private String delayPeriod;
}
字段注解
package com.wanmi.sbc.auction.pdf;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface PdfValue {
String colName() default "";
int typeFile() default 0;//0-普通 不用边框 1-有边框
}