Files
DPAPP/src/main/java/com/example/sso/dao/Photo.java
2026-01-19 14:36:25 +08:00

437 lines
15 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.example.sso.dao;
import com.itextpdf.io.image.ImageData;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.colors.DeviceRgb;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Canvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Image;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.kernel.events.Event;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class Photo {
// 使用 ThreadLocal 存储每个线程的独立变量
private static final ThreadLocal<PdfDocument> pdfDocThreadLocal = new ThreadLocal<>();
private static final ThreadLocal<Document> documentThreadLocal = new ThreadLocal<>();
private static final ThreadLocal<String> currentPdfPathThreadLocal = new ThreadLocal<>();
private static final ThreadLocal<PdfFont> chineseFontThreadLocal = new ThreadLocal<>();
// 存储每页的页脚文本使用ThreadLocal确保线程安全
private static final ThreadLocal<List<FooterText>> footerTextsThreadLocal = new ThreadLocal<>();
// 页脚文本类
private static class FooterText {
String text;
float x;
float y;
DeviceRgb color;
FooterText(String text, float x, float y, DeviceRgb color) {
this.text = text;
this.x = x;
this.y = y;
this.color = color;
}
}
// 页脚事件处理器
private static class FooterEventHandler implements IEventHandler {
@Override
public void handleEvent(Event event) {
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
PdfCanvas canvas = new PdfCanvas(docEvent.getPage());
Rectangle pageSize = docEvent.getPage().getPageSize();
// 获取当前线程的字体和页脚文本
PdfFont chineseFont = chineseFontThreadLocal.get();
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (chineseFont == null || footerTexts == null || footerTexts.isEmpty()) {
canvas.release();
return;
}
// 创建Canvas用于绘制
Canvas pageCanvas = new Canvas(canvas, pageSize);
// 绘制所有页脚文本
for (FooterText footerText : footerTexts) {
Paragraph paragraph = new Paragraph(footerText.text)
.setFont(chineseFont)
.setFontSize(12);
if (footerText.color != null) {
paragraph.setFontColor(footerText.color);
}
// 在指定位置绘制文本
pageCanvas.showTextAligned(
paragraph,
footerText.x,
footerText.y,
TextAlignment.LEFT,
VerticalAlignment.BOTTOM
);
}
canvas.release();
}
}
/**
* 开始创建PDF
*/
public static void startPDF(String pdfPath) throws IOException {
// 获取当前线程的变量
PdfDocument pdfDoc = pdfDocThreadLocal.get();
Document document = documentThreadLocal.get();
// 如果已经存在,先关闭
if (pdfDoc != null || document != null) {
closePDF();
}
// 创建新的PDF文档
currentPdfPathThreadLocal.set(pdfPath);
PdfWriter writer = new PdfWriter(pdfPath);
pdfDoc = new PdfDocument(writer);
// 注册页脚事件处理器
FooterEventHandler footerHandler = new FooterEventHandler();
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, footerHandler);
// 使用标准A4纸
document = new Document(pdfDoc, PageSize.A4, false);
document.setMargins(0, 0, 0, 0);
// 初始化中文字体
PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
// 初始化页脚文本列表
footerTextsThreadLocal.set(new ArrayList<>());
// 保存到ThreadLocal
pdfDocThreadLocal.set(pdfDoc);
documentThreadLocal.set(document);
chineseFontThreadLocal.set(chineseFont);
System.out.println(Thread.currentThread().getName() + " 开始创建PDF: " + pdfPath);
}
/**
* 设置页脚文本(会在每一页底部显示)
*/
public static void setFooterText(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
// 获取页脚文本列表
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (footerTexts == null) {
footerTexts = new ArrayList<>();
footerTextsThreadLocal.set(footerTexts);
}
// 清空原有页脚,添加新的页脚文本
footerTexts.clear();
footerTexts.add(new FooterText(text, 50F, 30F, (DeviceRgb) DeviceRgb.BLACK));
System.out.println(Thread.currentThread().getName() + " 已设置页脚文本: " + text);
}
/**
* 添加图片章节
*/
public static void appendImageSection(String imagePath) throws IOException {
Document document = documentThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
// 添加图片
if (imagePath != null && new File(imagePath).exists()) {
ImageData imageData = ImageDataFactory.create(imagePath);
Image image = new Image(imageData);
image.setHorizontalAlignment(com.itextpdf.layout.properties.HorizontalAlignment.CENTER);
image.setMarginTop(5);
image.setMarginBottom(5);
image.setHeight(200);
image.setWidth(200);
document.add(image);
}
System.out.println(Thread.currentThread().getName() + " 已添加图片章节");
}
/**
* 添加文本章节
*/
public static void appendTextSection(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
document.add(new Paragraph(text)
.setFont(chineseFont)
.setFontSize(20)
.setBold()
.setMarginTop(20));
System.out.println(Thread.currentThread().getName() + " 已添加文本章节");
}
public static void TextAlignment(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
// 创建段落并设置居中对齐
Paragraph paragraph = new Paragraph(text)
.setFont(chineseFont)
.setFontSize(20)
.setBold()
.setMarginTop(20)
.setTextAlignment(TextAlignment.CENTER);
document.add(paragraph);
System.out.println(Thread.currentThread().getName() + " 已添加文本章节");
}
public static void appendTextSections(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (footerTexts == null) {
footerTexts = new ArrayList<>();
footerTextsThreadLocal.set(footerTexts);
}
// 添加白色文本
footerTexts.add(new FooterText(text, 475F, 25f, (DeviceRgb) DeviceRgb.WHITE));
System.out.println(Thread.currentThread().getName() + " 已添加白色页脚文本: " + text);
}
public static void appendTextSections1(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (footerTexts == null) {
footerTexts = new ArrayList<>();
footerTextsThreadLocal.set(footerTexts);
}
// 添加黑色文本
footerTexts.add(new FooterText(text, 310f, 25f, null));
System.out.println(Thread.currentThread().getName() + " 已添加黑色页脚文本: " + text);
}
public static void appendTextSectionss(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (footerTexts == null) {
footerTexts = new ArrayList<>();
footerTextsThreadLocal.set(footerTexts);
}
// 添加白色文本
footerTexts.add(new FooterText(text, 400F, 50F, (DeviceRgb) DeviceRgb.WHITE));
System.out.println(Thread.currentThread().getName() + " 已添加白色页脚文本: " + text);
}
public static void appendTextSectionss1(String text) throws IOException {
Document document = documentThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document == null) {
throw new IllegalStateException("请先调用 startPDF() 方法");
}
if (chineseFont == null) {
chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
chineseFontThreadLocal.set(chineseFont);
}
List<FooterText> footerTexts = footerTextsThreadLocal.get();
if (footerTexts == null) {
footerTexts = new ArrayList<>();
footerTextsThreadLocal.set(footerTexts);
}
// 添加黑色文本
footerTexts.add(new FooterText(text, 310, 50, null));
System.out.println(Thread.currentThread().getName() + " 已添加黑色页脚文本: " + text);
}
/**
* 添加分页符
*/
public static void addPageBreak() {
Document document = documentThreadLocal.get();
if (document != null) {
document.add(new com.itextpdf.layout.element.AreaBreak());
System.out.println(Thread.currentThread().getName() + " 已添加分页符");
}
}
/**
* 关闭并保存PDF
*/
public static void closePDF() {
// 获取当前线程的变量
Document document = documentThreadLocal.get();
PdfDocument pdfDoc = pdfDocThreadLocal.get();
String currentPdfPath = currentPdfPathThreadLocal.get();
PdfFont chineseFont = chineseFontThreadLocal.get();
if (document != null) {
document.close();
documentThreadLocal.remove();
}
if (pdfDoc != null) {
pdfDoc.close();
pdfDocThreadLocal.remove();
}
if (chineseFont != null) {
chineseFontThreadLocal.remove();
}
if (currentPdfPath != null) {
System.out.println(Thread.currentThread().getName() + " PDF已保存: " + currentPdfPath);
currentPdfPathThreadLocal.remove();
}
}
/**
* 快速使用示例
*/
public static void createPDFWithMultipleSections(String pdfPath) throws IOException {
startPDF(pdfPath);
try {
// 添加各种内容
appendTextSection("这是文档的第一部分\n包含一些介绍性的文字");
appendImageSection("image1.jpg");
appendTextSection("这是图片1的描述文字");
appendImageSection("image2.png");
appendTextSection("这是图片2的描述文字");
} finally {
// 确保资源被释放
closePDF();
}
}
public static void createSimpleChinesePDF() throws IOException {
// 这个方法不使用ThreadLocal变量因为它自己创建PDF
// 1. 创建PDF
PdfWriter writer = new PdfWriter("D:\\下载模板\\a.pdf");
PdfDocument pdfDoc = new PdfDocument(writer);
Document document = new Document(pdfDoc);
// 2. 加载中文字体必须要有font-asian依赖
PdfFont chineseFont = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
// 3. 添加中文内容
Paragraph title = new Paragraph("中文标题")
.setFont(chineseFont)
.setFontSize(20)
.setBold();
document.add(title);
Paragraph content = new Paragraph("这是中文内容,可以正常显示。")
.setFont(chineseFont)
.setFontSize(12);
document.add(content);
// 4. 关闭文档
document.close();
pdfDoc.close();
System.out.println("PDF创建完成");
}
/**
* 测试多线程并发
*/
}