思路
- 先通过freemarker模板将数据渲染出来生成html静态页面
- 通过itext的html2pdf组件将html页面转换成pdf
- 通过itext包下的ColumnText.showTextAligned(final PdfContentByte canvas, final int alignment, final Phrase phrase, final float x, final float y, final float rotation)方法添加循环水印
依赖
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>html2pdf</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>font-asian</artifactId>
<version>7.0.3</version>
</dependency>
工具类
@Slf4j
@Component
public class PdfUtil {
@Autowired
private FreeMarkerConfigurer freeMarkerConfigurer;
private static ConverterProperties converterProperties;
static {
converterProperties = new ConverterProperties();
// 提供解析用的字体
FontProvider fp = new FontProvider();
// 添加标准字体库、无中文
fp.addStandardPdfFonts();
try {
// 自定义字体路径、解决中文
fp.addDirectory(ResourceUtils.getURL(ResourceUtils.CLASSPATH_URL_PREFIX + "static/fonts").getPath());
} catch (FileNotFoundException e) {
log.error("加载字体库异常");
}
converterProperties.setFontProvider(fp);
}
/**
* freemarker渲染html
*/
public String renderTrainDutyReport(Map<String, Object> data) {
try (Writer out = new StringWriter()) {
// 获取模板,并设置编码方式
Template template = freeMarkerConfigurer.getConfiguration().getTemplate("train_duty.ftl");
// 合并数据模型与模板
//将合并后的数据和模板写入到流中,这里使用的字符流
template.process(data, out);
out.flush();
return out.toString();
} catch (Exception e) {
log.error("加载freemarker模板失败");
throw new ServiceException("加载freemarker模板失败");
}
}
/**
* html2pdf
*
* @param html html字符串
* @return byte[]
* @throws IOException IOException
*/
public byte[] convert(String html) throws IOException {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
HtmlConverter.convertToPdf(html, outputStream, converterProperties);
byte[] result = outputStream.toByteArray();
outputStream.close();
return result;
}
/**
* 循环增加水印
* @param source 源文件
* @param text 水印文字
* @return 加过水印的文件字节数组
* @throws Exception 异常
*/
public byte[] addWaterMark(byte[] source, String text) throws Exception {
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
Font watermarkFont = FontFactory
.getFont(ResourceUtils.getURL(
ResourceUtils.CLASSPATH_URL_PREFIX + "static/fonts").getPath()+"/simhei.ttf",
BaseFont.IDENTITY_H, BaseFont.SUPERSCRIPT_SIZE,
Font.BOLD, new GrayColor(0.9f));
PdfReader reader = new PdfReader(source);
PdfStamper stamp = new PdfStamper(reader, outputStream);
PdfContentByte under;
int pageSize = reader.getNumberOfPages();// 原pdf文件的总页数
for (int i = 1; i <= pageSize; i++) {
under = stamp.getUnderContent(i);// 水印在之前文本下
for (int m = 0; m < 5; m++) {
for (int n = 0; n < 5; n++) {
ColumnText.showTextAligned(under, Element.ALIGN_CENTER, new Phrase(text,watermarkFont),
(50.5f + m * 150), (40.0f + n * 150),45);
}
}
}
stamp.close();// 关闭
reader.close();
byte[] bytes = outputStream.toByteArray();
// TODO
// Path path = Paths.get("D:\\1111.pdf");
// Files.write(path, bytes);
outputStream.close();
return bytes;
}
}