新增pdf页码
parent
1739cfadef
commit
b8c07682b9
|
|
@ -7,6 +7,7 @@ import com.gunshi.project.hsz.mapper.ForecastProjectMapper;
|
|||
import com.gunshi.project.hsz.model.ForecastProject;
|
||||
import com.gunshi.project.hsz.model.ForecastResults;
|
||||
import com.itextpdf.io.font.PdfEncodings;
|
||||
import com.itextpdf.kernel.colors.Color;
|
||||
import com.itextpdf.kernel.colors.DeviceRgb;
|
||||
import com.itextpdf.kernel.events.Event;
|
||||
import com.itextpdf.kernel.events.IEventHandler;
|
||||
|
|
@ -19,6 +20,7 @@ import com.itextpdf.kernel.pdf.PdfDocument;
|
|||
import com.itextpdf.kernel.pdf.PdfPage;
|
||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
|
||||
import com.itextpdf.layout.Canvas;
|
||||
import com.itextpdf.layout.Document;
|
||||
import com.itextpdf.layout.element.Cell;
|
||||
|
|
@ -32,6 +34,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
|
|
@ -92,18 +95,115 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
|||
}
|
||||
|
||||
public void generatePdf(ForecastProject project, ZipOutputStream outputStream) {
|
||||
// 第一次生成:获取总页码
|
||||
int totalPages = calculateTotalPages(project);
|
||||
|
||||
// 使用ByteArrayOutputStream作为缓冲
|
||||
// 第二次生成:正式生成带页码的PDF
|
||||
generatePdfWithPageNumbers(project, outputStream, totalPages);
|
||||
}
|
||||
|
||||
// 第一次生成:计算总页码
|
||||
private int calculateTotalPages(ForecastProject project) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
PdfDocument pdfDoc = null;
|
||||
Document document = null;
|
||||
try{
|
||||
PdfWriter writer = new PdfWriter(baos);
|
||||
pdfDoc = new PdfDocument(writer);
|
||||
document = new Document(pdfDoc,PageSize.A4.rotate());
|
||||
|
||||
try (PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument pdfDoc = new PdfDocument(writer);
|
||||
Document document = new Document(pdfDoc, PageSize.A4.rotate())) {
|
||||
|
||||
// 设置字体
|
||||
String fontPath = "/fonts/ChineseFonts.ttf";
|
||||
PdfFont font = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H);
|
||||
|
||||
// 添加内容(但不添加页码)
|
||||
addContentToDocument(document, font, project, false);
|
||||
|
||||
// 返回总页数
|
||||
return pdfDoc.getNumberOfPages();
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("计算PDF页数失败", e);
|
||||
throw new RuntimeException("PDF页数计算失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 第二次生成:正式生成带页码的PDF
|
||||
private void generatePdfWithPageNumbers(ForecastProject project, ZipOutputStream outputStream, int totalPages) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
try (PdfWriter writer = new PdfWriter(baos);
|
||||
PdfDocument pdfDoc = new PdfDocument(writer);
|
||||
Document document = new Document(pdfDoc, PageSize.A4.rotate())) {
|
||||
|
||||
// 设置字体
|
||||
String fontPath = "/fonts/ChineseFonts.ttf";
|
||||
PdfFont font = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H);
|
||||
|
||||
// 添加页码处理器
|
||||
PageNumberEventHandler eventHandler = new PageNumberEventHandler(font, totalPages);
|
||||
pdfDoc.addEventHandler(PdfDocumentEvent.END_PAGE, eventHandler);
|
||||
|
||||
// 添加内容
|
||||
addContentToDocument(document, font, project, true);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("生成PDF失败", e);
|
||||
throw new RuntimeException("PDF生成失败");
|
||||
}
|
||||
|
||||
// 在try-with-resources块外获取字节数组并写入输出流
|
||||
try {
|
||||
byte[] pdfBytes = baos.toByteArray();
|
||||
outputStream.write(pdfBytes);
|
||||
} catch (IOException e) {
|
||||
log.error("写入ZIP失败", e);
|
||||
throw new RuntimeException("写入ZIP失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 页码事件处理器 - 简化版本
|
||||
private static class PageNumberEventHandler implements IEventHandler {
|
||||
private final PdfFont font;
|
||||
private final int totalPages;
|
||||
|
||||
public PageNumberEventHandler(PdfFont font, int totalPages) {
|
||||
this.font = font;
|
||||
this.totalPages = totalPages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleEvent(Event event) {
|
||||
PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
|
||||
PdfDocument pdfDoc = docEvent.getDocument();
|
||||
PdfPage page = docEvent.getPage();
|
||||
int currentPage = pdfDoc.getPageNumber(page);
|
||||
|
||||
// 获取页面尺寸
|
||||
Rectangle pageSize = page.getPageSize();
|
||||
|
||||
// 创建画布
|
||||
PdfCanvas pdfCanvas = new PdfCanvas(page.newContentStreamAfter(), page.getResources(), pdfDoc);
|
||||
|
||||
// 设置页码文本
|
||||
String pageText = "第 " + currentPage + " 页 / 共 " + totalPages + " 页";
|
||||
|
||||
// 直接使用PdfCanvas绘制文本(更简单的方式)
|
||||
pdfCanvas.beginText()
|
||||
.setFontAndSize(font, 10)
|
||||
.moveText((pageSize.getLeft() + pageSize.getRight()) / 2 - 50, pageSize.getBottom() + 20)
|
||||
.showText(pageText)
|
||||
.endText();
|
||||
|
||||
pdfCanvas.release();
|
||||
}
|
||||
}
|
||||
|
||||
// 添加内容到文档的公共方法
|
||||
private void addContentToDocument(Document document, PdfFont font, ForecastProject project, boolean addPageMargins) throws IOException {
|
||||
if (addPageMargins) {
|
||||
// 为页码预留底部边距
|
||||
document.setMargins(36, 36, 36, 50);
|
||||
}
|
||||
|
||||
// 第一行:基本信息
|
||||
Paragraph header1 = new Paragraph()
|
||||
.add("预见期(小时): " + (project.getForecastPeriod() != null ? project.getForecastPeriod() : "无") + " ")
|
||||
|
|
@ -131,7 +231,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
|||
|
||||
// 第三行:数据表格
|
||||
if (CollectionUtils.isNotEmpty(project.getVoList())) {
|
||||
Table table = new Table(9); // 10列
|
||||
Table table = new Table(9);
|
||||
table.setWidth(UnitValue.createPercentValue(100));
|
||||
|
||||
// 表头
|
||||
|
|
@ -162,21 +262,6 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
|||
} else {
|
||||
document.add(new Paragraph("无预报结果数据").setFont(font));
|
||||
}
|
||||
// 5. 关闭文档(关键:先关闭Document,再关闭PdfDocument)
|
||||
document.close();
|
||||
pdfDoc.close();
|
||||
} catch (Exception e) {
|
||||
log.error("生成PDF失败", e);
|
||||
throw new RuntimeException("PDF生成失败");
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] pdfBytes = baos.toByteArray();
|
||||
outputStream.write(pdfBytes);
|
||||
}catch (IOException e){
|
||||
log.error("写入ZIP失败", e);
|
||||
throw new RuntimeException("写入ZIP失败");
|
||||
}
|
||||
}
|
||||
|
||||
// 辅助方法:创建表格单元格
|
||||
|
|
|
|||
Loading…
Reference in New Issue