新增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.ForecastProject;
|
||||||
import com.gunshi.project.hsz.model.ForecastResults;
|
import com.gunshi.project.hsz.model.ForecastResults;
|
||||||
import com.itextpdf.io.font.PdfEncodings;
|
import com.itextpdf.io.font.PdfEncodings;
|
||||||
|
import com.itextpdf.kernel.colors.Color;
|
||||||
import com.itextpdf.kernel.colors.DeviceRgb;
|
import com.itextpdf.kernel.colors.DeviceRgb;
|
||||||
import com.itextpdf.kernel.events.Event;
|
import com.itextpdf.kernel.events.Event;
|
||||||
import com.itextpdf.kernel.events.IEventHandler;
|
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.PdfPage;
|
||||||
import com.itextpdf.kernel.pdf.PdfWriter;
|
import com.itextpdf.kernel.pdf.PdfWriter;
|
||||||
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
|
||||||
|
import com.itextpdf.kernel.pdf.colorspace.PdfColorSpace;
|
||||||
import com.itextpdf.layout.Canvas;
|
import com.itextpdf.layout.Canvas;
|
||||||
import com.itextpdf.layout.Document;
|
import com.itextpdf.layout.Document;
|
||||||
import com.itextpdf.layout.element.Cell;
|
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.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -92,18 +95,115 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generatePdf(ForecastProject project, ZipOutputStream outputStream) {
|
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();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
PdfDocument pdfDoc = null;
|
|
||||||
Document document = null;
|
try (PdfWriter writer = new PdfWriter(baos);
|
||||||
try{
|
PdfDocument pdfDoc = new PdfDocument(writer);
|
||||||
PdfWriter writer = new PdfWriter(baos);
|
Document document = new Document(pdfDoc, PageSize.A4.rotate())) {
|
||||||
pdfDoc = new PdfDocument(writer);
|
|
||||||
document = new Document(pdfDoc,PageSize.A4.rotate());
|
|
||||||
// 设置字体
|
// 设置字体
|
||||||
String fontPath = "/fonts/ChineseFonts.ttf";
|
String fontPath = "/fonts/ChineseFonts.ttf";
|
||||||
PdfFont font = PdfFontFactory.createFont(fontPath, PdfEncodings.IDENTITY_H);
|
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()
|
Paragraph header1 = new Paragraph()
|
||||||
.add("预见期(小时): " + (project.getForecastPeriod() != null ? project.getForecastPeriod() : "无") + " ")
|
.add("预见期(小时): " + (project.getForecastPeriod() != null ? project.getForecastPeriod() : "无") + " ")
|
||||||
|
|
@ -131,7 +231,7 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
|
|
||||||
// 第三行:数据表格
|
// 第三行:数据表格
|
||||||
if (CollectionUtils.isNotEmpty(project.getVoList())) {
|
if (CollectionUtils.isNotEmpty(project.getVoList())) {
|
||||||
Table table = new Table(9); // 10列
|
Table table = new Table(9);
|
||||||
table.setWidth(UnitValue.createPercentValue(100));
|
table.setWidth(UnitValue.createPercentValue(100));
|
||||||
|
|
||||||
// 表头
|
// 表头
|
||||||
|
|
@ -162,21 +262,6 @@ public class ForecastProjectService extends ServiceImpl<ForecastProjectMapper, F
|
||||||
} else {
|
} else {
|
||||||
document.add(new Paragraph("无预报结果数据").setFont(font));
|
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