方法一
依賴
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.13</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext-asian</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
代碼參考
PDFUtil工具類
/**
* 根據模板生成pdf
*@param pdfName 文件名
* @param data Map(String,Object)
* @return 文件保存全路徑文件
*/
import cn.hutool.core.date.DateUtil;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.pdf.AcroFields;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfStamper;
import lombok.extern.slf4j.Slf4j;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
/**
* @author lin
*/
@Slf4j
public class PDFUtil {
public static String createPDF(String pdfName, Map<String, Object> data) {
//靜態方法只能使用匿名類
String file = new Object() {
public String getPath() {
return Objects.requireNonNull(this.getClass().getResource("/")).getPath();
}
}.getPath();
System.out.println(file);
String dateFolder = DateUtil.today();
String folderPath = file + File.separator + dateFolder;
//創建上傳文件目錄
File folder = new File(folderPath);
if (!folder.exists()) {
folder.mkdirs();
}
//設置文件名
String fileName = "_"+pdfName + ".pdf";
String savePath = folderPath + File.separator +DateUtil.today() + fileName;
try {
PdfReader reader = new PdfReader(file+"/TEMP.pdf");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
PdfStamper ps = new PdfStamper(reader, bos);
AcroFields s = ps.getAcroFields();
//TTC字體一般有多個所以選擇正常的加載
BaseFont bfChinese = BaseFont.createFont(file+"/MSYH.TTC,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
//設置編碼格式
s.addSubstitutionFont(bfChinese);
//這點可以直接傳對象,但是怕變動,所以map好自定義一個值
for (String key : data.keySet()) {
if (data.get(key) != null) {
s.setField(key, data.get(key).toString());
}
}
ps.setFormFlattening(true);
ps.close();
FileOutputStream fos = new FileOutputStream(savePath);
fos.write(bos.toByteArray());
fos.flush();
fos.close();
return savePath;
} catch (IOException | DocumentException e) {
log.error("讀取文件異常");
e.printStackTrace();
return "error";
}
}
}
import cn.hutool.core.bean.BeanUtil;
import com.example.demopdf.entry.PdfData;
import com.example.demopdf.utils.PDFUtil;
import java.util.Map;
/**
* @program: cherrypro
* @description:
* @author: lin
* @create: 2021-06-15 23:56
*/
public class TestDemo {
public static void main(String[] args) {
//你可以直接構造,我這里建造者模式
PdfData data = PdfData.builder()
.text1("XXXXX保險")
.text2("1111111111111111111")
.text3("一個小朋友")
.text4("女")
.text5("24")
.text6("1997-01-05")
.text7("12345619951215741X")
.text8("185")
.text9("45")
.text10(" ")
.text11(" ")
.text12(" ")
.text13("我希望你讀很多書,走很遠的路。 我希望你愛很多人,
也被很多人愛。 我希望你走過人山人海,也遍覽山河湖海。我希望你看紙質書,送手寫的祝福。
我要你獨立堅強溫暖明亮, 我要你在這寡淡的世上,深情的活。")
.text14("木木")
.text15("2021")
.text16("07")
.text17("04")
//這個選擇框模版有bug,所以默認全部打勾,不需要的取消
.ch1("false")
.ch4("false")
.build();
Map<String, Object> map = BeanUtil.beanToMap(data);
String s = PDFUtil.createPDF("ayi",map);
System.out.println(s);
}
}
模板圖片
數據域圖片
生成結果
后記:做這個坑在於checkbox
,選擇時候和理想不一樣,代碼操作選擇就是×
,所以反其道行之,這個版本做的並不滿意,希望那位小朋友順利搞完
有空的話,會升級下itextpdf
版本,官方已經停止5.0
,現在推薦7.0
,的確7.0
簡單,之后會放在GitHub。
方法二
pom依賴
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.2</version>
</dependency>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.itextpdf/itext7-core -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>7.1.15</version>
<type>pom</type>
</dependency>
PDFUtil工具類
package com.example.demopdf.utils;
import cn.hutool.core.bean.BeanUtil;
import com.example.demopdf.entry.PdfData;
import com.itextpdf.forms.PdfAcroForm;
import com.itextpdf.forms.fields.PdfFormField;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
/**
* iText Pdf屬性表單數據填充
*/
public class PDFUtil {
/**
* 簡單文本填充
*
* @param src 原始文件路徑
* @param out 輸出文件路徑
* @param map 填充數據
* @return
* @throws Exception
*/
public static byte[] fileProcess(String src, String out, Map<String, Object> map) throws Exception {
//輸出流
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
//獲取文檔
PdfDocument pdfDoc = new PdfDocument(new PdfReader(new File(src)), new PdfWriter(new File(out)));
//轉換為表單
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, false);
//屬性填充
for (Map.Entry<String, Object> entry : map.entrySet()) {
form.getField(entry.getKey()).setValue((String) entry.getValue());
}
//鎖定字段
form.flattenFields();
pdfDoc.close();
return outputStream.toByteArray();
}
public static void main(String[] args) throws Exception {
String file = new Object() {
public String getPath() {
return Objects.requireNonNull(this.getClass().getResource("/")).getPath();
}
}.getPath();
PdfData data = PdfData.builder()
.text1("xxxxxxx保險")
.text2("1111111111111111111")
.text3("xxx")
.text4("女")
.text5("24")
.text6("1997-01-05")
.text7("12345619951215741X")
.text8("185")
.text9("45")
.text10(" ")
.text11(" ")
.text12(" ")
.text13("我希望你讀很多書,走很遠的路。 我希望你愛很多人,也被很多人愛。 我希望你走過人山人海,也遍覽山河湖海。 我希望你看紙質書,送手寫的祝福。 我要你獨立堅強溫暖明亮, 我要你在這寡淡的世上,深情的活。")
.text14("木木")
.text15("2021")
.text16("07")
.text17("04")
//這個選擇框模版好像不對,但就是這個意思,我忘記對勾了
.ch1("on")
.ch2("off")
.ch3("off")
.ch4("on")
.ch15("是")
.ch16("on")
.build();
Map<String, Object> map = BeanUtil.beanToMap(data);
String local = file + "Temp.pdf";
String pdf = file + "demo.pdf";
byte[] strings = fileProcess(local, pdf, map);
}
}