|
|
@ -4,28 +4,54 @@ import com.google.gson.Gson; |
|
|
|
import com.google.gson.reflect.TypeToken; |
|
|
|
import com.itextpdf.forms.PdfAcroForm; |
|
|
|
import com.itextpdf.forms.fields.PdfFormField; |
|
|
|
import com.itextpdf.io.font.FontProgram; |
|
|
|
import com.itextpdf.io.font.FontProgramFactory; |
|
|
|
import com.itextpdf.io.font.PdfEncodings; |
|
|
|
import com.itextpdf.io.font.TrueTypeCollection; |
|
|
|
import com.itextpdf.kernel.font.PdfFont; |
|
|
|
import com.itextpdf.kernel.font.PdfFontFactory; |
|
|
|
import com.itextpdf.kernel.pdf.PdfDocument; |
|
|
|
import com.itextpdf.kernel.pdf.PdfName; |
|
|
|
import com.itextpdf.kernel.pdf.PdfReader; |
|
|
|
import com.itextpdf.kernel.pdf.PdfWriter; |
|
|
|
import lombok.extern.slf4j.Slf4j; |
|
|
|
import org.springframework.beans.factory.annotation.Value; |
|
|
|
import org.springframework.stereotype.Component; |
|
|
|
|
|
|
|
import java.awt.*; |
|
|
|
import java.io.File; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.lang.reflect.Field; |
|
|
|
import java.lang.reflect.Type; |
|
|
|
import java.net.MalformedURLException; |
|
|
|
import java.net.URL; |
|
|
|
import java.util.HashMap; |
|
|
|
import java.util.Map; |
|
|
|
|
|
|
|
import static com.itextpdf.kernel.pdf.PdfName.BaseFont; |
|
|
|
|
|
|
|
/** |
|
|
|
* @author Tanzs |
|
|
|
* @date 2025/2/19 下午3:29 |
|
|
|
* @description PDF表单填充工具类 |
|
|
|
*/ |
|
|
|
@Component |
|
|
|
@Slf4j |
|
|
|
public class PdfFormUtils { |
|
|
|
|
|
|
|
private static final Gson gson = new Gson(); |
|
|
|
|
|
|
|
// 本地使用调试字体路径 |
|
|
|
private static final String TEST_FONT_PATH = "/Users/tanzs/Documents/fonts/simsun.ttc,0"; |
|
|
|
|
|
|
|
// TODO 环境变量获取文字路径,重新部署需要复制 resource 下的字体文件到指定路径 |
|
|
|
@Value(value = "${jeecg.path.fonts}") |
|
|
|
private String DEFAULT_FONT_PATH; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 通过 pdf 文本域拼接 PDF 表单 |
|
|
@ -42,19 +68,26 @@ public class PdfFormUtils { |
|
|
|
// 获取表单 |
|
|
|
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); |
|
|
|
|
|
|
|
// 填写表单字段 |
|
|
|
// 打印所有字段名称 |
|
|
|
Map<String, PdfFormField> fields = form.getAllFormFields(); |
|
|
|
for (String fieldName : fields.keySet()) { |
|
|
|
System.out.println("Field name: " + fieldName); |
|
|
|
} |
|
|
|
// 创建字体 |
|
|
|
PdfFont baseFont = PdfFontFactory.createFont(TEST_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); |
|
|
|
|
|
|
|
// 填写表单字段 |
|
|
|
for (Map.Entry<String, String> entry : formData.entrySet()) { |
|
|
|
String fieldName = entry.getKey(); |
|
|
|
String fieldValue = entry.getValue(); |
|
|
|
|
|
|
|
// 确保字段存在并填写值 |
|
|
|
if (fields.containsKey(fieldName)) { |
|
|
|
fields.get(fieldName).setValue(fieldValue); |
|
|
|
fields.get(fieldName).setFontSize(fontSize); // 设置字体大小 |
|
|
|
PdfFormField field = fields.get(fieldName); |
|
|
|
if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 |
|
|
|
field.setValue(fieldValue); |
|
|
|
field.setFont(baseFont); |
|
|
|
field.setFontSize(fontSize); |
|
|
|
} else { |
|
|
|
System.out.println("Field not found or not a text field: " + fieldName); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -70,34 +103,39 @@ public class PdfFormUtils { |
|
|
|
/** |
|
|
|
* 通过 pdf 文本域拼接 PDF 表单 |
|
|
|
* @param templateUrl PDF 表单文件 URL,例如 "https://example.com/template.pdf" |
|
|
|
* @param outputPath 填充后的 PDF 文件路径 |
|
|
|
* @param outputFilePath 填充后的 PDF 文件路径 |
|
|
|
* @param formData 填充的数据,键为表单字段名称,值为填充的值 |
|
|
|
* @param fontSize 字体大小 |
|
|
|
*/ |
|
|
|
public static void fillPdfFormFromUrl(String templateUrl, String outputPath, Map<String, String> formData, float fontSize) { |
|
|
|
public void fillPdfFormFromUrl(String templateUrl, String outputFilePath, Map<String, String> formData, float fontSize) { |
|
|
|
try { |
|
|
|
// 从 URL 获取输入流 |
|
|
|
URL url = new URL(templateUrl); |
|
|
|
try (InputStream templateInputStream = url.openStream(); |
|
|
|
PdfWriter writer = new PdfWriter(outputPath); |
|
|
|
PdfWriter writer = new PdfWriter(outputFilePath); |
|
|
|
PdfDocument pdfDoc = new PdfDocument(new PdfReader(templateInputStream), writer)) { |
|
|
|
|
|
|
|
// 获取表单 |
|
|
|
PdfAcroForm form = PdfAcroForm.getAcroForm(pdfDoc, true); |
|
|
|
|
|
|
|
// 填写表单字段 |
|
|
|
// 打印所有字段名称 |
|
|
|
Map<String, PdfFormField> fields = form.getAllFormFields(); |
|
|
|
for (String fieldName : fields.keySet()) { |
|
|
|
System.out.println("Field name: " + fieldName); |
|
|
|
log.debug("Field name: " + fieldName); |
|
|
|
} |
|
|
|
// 创建字体 |
|
|
|
PdfFont baseFont = PdfFontFactory.createFont(DEFAULT_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); |
|
|
|
|
|
|
|
// 填写表单字段 |
|
|
|
for (Map.Entry<String, String> entry : formData.entrySet()) { |
|
|
|
String fieldName = entry.getKey(); |
|
|
|
String fieldValue = entry.getValue(); |
|
|
|
|
|
|
|
// 确保字段存在并填写值 |
|
|
|
if (fields.containsKey(fieldName)) { |
|
|
|
fields.get(fieldName).setValue(fieldValue); |
|
|
|
fields.get(fieldName).setFontSize(fontSize); // 设置字体大小 |
|
|
|
PdfFormField field = fields.get(fieldName); |
|
|
|
if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 |
|
|
|
field.setValue(fieldValue); |
|
|
|
field.setFont(baseFont); |
|
|
|
field.setFontSize(fontSize); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -106,20 +144,28 @@ public class PdfFormUtils { |
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
|
e.printStackTrace(); |
|
|
|
throw new RuntimeException("pdf合同生成失败,请稍后重试!"); |
|
|
|
} |
|
|
|
|
|
|
|
} catch (IOException e) { |
|
|
|
e.printStackTrace(); |
|
|
|
throw new RuntimeException("pdf合同生成失败,请稍后重试!"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static void fillPdfFormFromUrl2(String templateUrl, String outputPath, Map<String, String> formData, float fontSize) { |
|
|
|
/** |
|
|
|
* 通过 pdf 文本域拼接 PDF 表单 |
|
|
|
* @param templateUrl PDF 表单文件 URL,例如 "https://example.com/template.pdf" |
|
|
|
* @param outputFilePath 填充后的 PDF 文件路径 |
|
|
|
* @param formData 填充的数据,键为表单字段名称,值为填充的值 |
|
|
|
* @param fontSize 字体大小 |
|
|
|
*/ |
|
|
|
public static void fillPdfFormFromUrlLocal(String templateUrl, String outputFilePath, Map<String, String> formData, float fontSize) { |
|
|
|
try { |
|
|
|
// 从 URL 获取输入流 |
|
|
|
URL url = new URL(templateUrl); |
|
|
|
try (InputStream templateInputStream = url.openStream(); |
|
|
|
PdfWriter writer = new PdfWriter(outputPath); |
|
|
|
PdfWriter writer = new PdfWriter(outputFilePath); |
|
|
|
PdfDocument pdfDoc = new PdfDocument(new PdfReader(templateInputStream), writer)) { |
|
|
|
|
|
|
|
// 获取表单 |
|
|
@ -130,6 +176,8 @@ public class PdfFormUtils { |
|
|
|
for (String fieldName : fields.keySet()) { |
|
|
|
System.out.println("Field name: " + fieldName); |
|
|
|
} |
|
|
|
// 创建字体 |
|
|
|
PdfFont baseFont = PdfFontFactory.createFont(TEST_FONT_PATH, PdfEncodings.IDENTITY_H, PdfFontFactory.EmbeddingStrategy.FORCE_EMBEDDED); |
|
|
|
|
|
|
|
// 填写表单字段 |
|
|
|
for (Map.Entry<String, String> entry : formData.entrySet()) { |
|
|
@ -139,6 +187,7 @@ public class PdfFormUtils { |
|
|
|
PdfFormField field = fields.get(fieldName); |
|
|
|
if (field != null && field.getFormType() == PdfName.Tx) { // 检查是否为文本字段 |
|
|
|
field.setValue(fieldValue); |
|
|
|
field.setFont(baseFont); |
|
|
|
field.setFontSize(fontSize); |
|
|
|
} else { |
|
|
|
System.out.println("Field not found or not a text field: " + fieldName); |
|
|
@ -158,6 +207,8 @@ public class PdfFormUtils { |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
* 实体类转换成Map |
|
|
|
* @param obj |
|
|
@ -189,21 +240,21 @@ public class PdfFormUtils { |
|
|
|
|
|
|
|
// 示例:调用此工具类 |
|
|
|
public static void main(String[] args) { |
|
|
|
String templatePath = "/Users/tanzs/Downloads/carT.pdf"; |
|
|
|
// String templateUrl = "https://jf.sh.189.cn/minio/gov-miniapp/order_pdf/carT.pdf"; |
|
|
|
// String templatePath = "/Users/tanzs/Downloads/carT.pdf"; |
|
|
|
String templateUrl = "https://img.augcl.com/temp/carT_1740226107035.pdf"; |
|
|
|
String outputPath = "/Users/tanzs/Downloads/carR.pdf"; |
|
|
|
float fontSize = 6.5f; // 设置字体大小 |
|
|
|
|
|
|
|
// 填写的数据 |
|
|
|
Map<String, String> formData = new HashMap<String, String>(); |
|
|
|
formData.put("cust_name", "张三"); |
|
|
|
formData.put("cust_phone", "123213"); |
|
|
|
formData.put("custName", "张三"); |
|
|
|
formData.put("custPhone", "123213"); |
|
|
|
formData.put("carNo", "京A12345"); |
|
|
|
formData.put("cust_address", "测试地址"); |
|
|
|
formData.put("custAddress", "测试地址"); |
|
|
|
|
|
|
|
// 调用工具类进行表单填写 |
|
|
|
fillPdfForm(templatePath, outputPath, formData, fontSize); |
|
|
|
// fillPdfFormFromUrl(templateUrl, outputPath, formData, fontSize); |
|
|
|
// fillPdfForm(templatePath, outputPath, formData, fontSize); |
|
|
|
fillPdfFormFromUrlLocal(templateUrl, outputPath, formData, fontSize); |
|
|
|
} |
|
|
|
|
|
|
|
} |