|
@@ -3,15 +3,18 @@ package com.etotem.cfc.service.impl;
|
|
|
import com.etotem.cfc.entity.FamilyFortuneReport;
|
|
import com.etotem.cfc.entity.FamilyFortuneReport;
|
|
|
import com.etotem.cfc.mapper.FamilyFortuneReportMapper;
|
|
import com.etotem.cfc.mapper.FamilyFortuneReportMapper;
|
|
|
import com.etotem.cfc.service.PdfReportService;
|
|
import com.etotem.cfc.service.PdfReportService;
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.PDDocument;
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.PDPage;
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.PDPageContentStream;
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.common.PDRectangle;
|
|
|
|
|
+import org.apache.pdfbox.pdmodel.font.PDType1Font;
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
import javax.annotation.Resource;
|
|
|
-import java.io.ByteArrayInputStream;
|
|
|
|
|
-import java.io.File;
|
|
|
|
|
-import java.io.FileOutputStream;
|
|
|
|
|
|
|
+import java.io.ByteArrayOutputStream;
|
|
|
import java.io.IOException;
|
|
import java.io.IOException;
|
|
|
import java.text.SimpleDateFormat;
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.Base64;
|
|
import java.util.Base64;
|
|
@@ -100,23 +103,38 @@ public class PdfReportServiceImpl implements PdfReportService {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
- * 构建简单 PDF 包装(占位实现 - 生产环境应使用 iText)
|
|
|
|
|
- * 这里返回一个带 PDF 头部的最小字节数组,确保文件可被识别为 PDF
|
|
|
|
|
|
|
+ * 构建周报 PDF(使用 PDFBox 渲染)
|
|
|
*/
|
|
*/
|
|
|
private byte[] buildSimplePdfFromImage(byte[] imageBytes, String element, String luckyDirection, String tip) {
|
|
private byte[] buildSimplePdfFromImage(byte[] imageBytes, String element, String luckyDirection, String tip) {
|
|
|
- // 简化方案:生成 PDF 占位文件
|
|
|
|
|
- // 实际项目中需要使用 iText 或 Apache PDFBox 进行完整 PDF 渲染
|
|
|
|
|
- String content = "家庭天盘周报\\n主导元素: " + safeText(element) +
|
|
|
|
|
- "\\n吉位: " + safeText(luckyDirection) +
|
|
|
|
|
- "\\n本周提示: " + safeText(tip);
|
|
|
|
|
-
|
|
|
|
|
- // 构建简单的 PDF 文档(最小可行实现)
|
|
|
|
|
- String pdfContent = "BT /F1 12 Tf 72 720 Td (Family Fortune Report) Tj ET\\n" +
|
|
|
|
|
- "BT /F1 10 Tf 72 700 Td (Element: " + safeText(element) + ") Tj ET\\n" +
|
|
|
|
|
- "BT /F1 10 Tf 72 685 Td (Lucky Direction: " + safeText(luckyDirection) + ") Tj ET\\n" +
|
|
|
|
|
- "BT /F1 10 Tf 72 670 Td (Tip: " + safeText(tip) + ") Tj ET\\n";
|
|
|
|
|
-
|
|
|
|
|
- return buildMinimalPdf(pdfContent, imageBytes.length);
|
|
|
|
|
|
|
+ try (PDDocument document = new PDDocument()) {
|
|
|
|
|
+ PDPage page = new PDPage(PDRectangle.A4);
|
|
|
|
|
+ document.addPage(page);
|
|
|
|
|
+ try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
|
|
|
|
|
+ contentStream.setFont(PDType1Font.HELVETICA_BOLD, 18);
|
|
|
|
|
+ contentStream.beginText();
|
|
|
|
|
+ contentStream.newLineAtOffset(50, 750);
|
|
|
|
|
+ contentStream.showText("家庭天盘周报");
|
|
|
|
|
+ contentStream.endText();
|
|
|
|
|
+
|
|
|
|
|
+ contentStream.setFont(PDType1Font.HELVETICA, 14);
|
|
|
|
|
+ contentStream.beginText();
|
|
|
|
|
+ contentStream.newLineAtOffset(50, 710);
|
|
|
|
|
+ contentStream.showText("主导元素: " + safeText(element));
|
|
|
|
|
+ contentStream.newLineAtOffset(0, -25);
|
|
|
|
|
+ contentStream.showText("吉位: " + safeText(luckyDirection));
|
|
|
|
|
+ contentStream.newLineAtOffset(0, -25);
|
|
|
|
|
+ contentStream.showText("本周提示: " + safeText(tip));
|
|
|
|
|
+ contentStream.endText();
|
|
|
|
|
+ }
|
|
|
|
|
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
|
|
|
+ document.save(baos);
|
|
|
|
|
+ return baos.toByteArray();
|
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
|
+ log.warn("PDF 生成失败,降级为文本: {}", e.getMessage());
|
|
|
|
|
+ return ("家庭天盘周报\n主导元素: " + element
|
|
|
|
|
+ + "\n吉位: " + luckyDirection
|
|
|
|
|
+ + "\n本周提示: " + tip).getBytes();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
private String safeText(String s) {
|
|
private String safeText(String s) {
|
|
@@ -124,43 +142,6 @@ public class PdfReportServiceImpl implements PdfReportService {
|
|
|
return s.replaceAll("[()\\\\]", "");
|
|
return s.replaceAll("[()\\\\]", "");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 构建最简单的 PDF 文档字节流
|
|
|
|
|
- */
|
|
|
|
|
- private byte[] buildMinimalPdf(String content, int imageLength) {
|
|
|
|
|
- StringBuilder pdf = new StringBuilder();
|
|
|
|
|
- pdf.append("%PDF-1.4\\n");
|
|
|
|
|
- pdf.append("1 0 obj\\n<< /Type /Catalog /Pages 2 0 R >>\\nendobj\\n");
|
|
|
|
|
- pdf.append("2 0 obj\\n<< /Type /Pages /Kids [3 0 R] /Count 1 >>\\nendobj\\n");
|
|
|
|
|
- pdf.append("3 0 obj\\n<< /Type /Page /Parent 2 0 R /MediaBox [0 0 612 792] /Contents 4 0 R /Resources << /Font << /F1 5 0 R >> >> >>\\nendobj\\n");
|
|
|
|
|
- pdf.append("4 0 obj\\n<< /Length ").append(content.length()).append(" >>\\nstream\\n").append(content).append("\\nendstream\\nendobj\\n");
|
|
|
|
|
- pdf.append("5 0 obj\\n<< /Type /Font /Subtype /Type1 /BaseFont /Helvetica >>\\nendobj\\n");
|
|
|
|
|
- pdf.append("xref\\n0 6\\n");
|
|
|
|
|
- pdf.append("0000000000 65535 f \\n");
|
|
|
|
|
- pdf.append("0000000009 00000 n \\n");
|
|
|
|
|
- pdf.append("0000000058 00000 n \\n");
|
|
|
|
|
- pdf.append("0000000111 00000 n \\n");
|
|
|
|
|
- pdf.append("0000000213 00000 n \\n");
|
|
|
|
|
- pdf.append("0000000").append(300 + content.length()).append(" 00000 n \\n");
|
|
|
|
|
- pdf.append("trailer\\n<< /Size 6 /Root 1 0 R >>\\n");
|
|
|
|
|
- pdf.append("startxref\\n").append(400 + content.length()).append("\\n");
|
|
|
|
|
- pdf.append("%%EOF\\n");
|
|
|
|
|
-
|
|
|
|
|
- // 注:当前公共 API 不支持中文嵌入,使用 ASCII-only 简化文本
|
|
|
|
|
- String generated = pdf.toString()
|
|
|
|
|
- .replace("\\n", System.lineSeparator())
|
|
|
|
|
- .replace("\\(", "(")
|
|
|
|
|
- .replace("\\)", ")");
|
|
|
|
|
-
|
|
|
|
|
- // 附带图片数据大小信息(用于文件大小计算)
|
|
|
|
|
- byte[] pdfBytes = generated.getBytes();
|
|
|
|
|
- // 拼接实际内容字节(生产环境应使用真正的 PDF 库)
|
|
|
|
|
- byte[] result = new byte[pdfBytes.length + imageLength];
|
|
|
|
|
- System.arraycopy(pdfBytes, 0, result, 0, pdfBytes.length);
|
|
|
|
|
- // 图片数据不直接嵌入简化 PDF(避免二进制截断问题)
|
|
|
|
|
- return result;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
private int getCurrentWeekNumber() {
|
|
private int getCurrentWeekNumber() {
|
|
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
|
java.util.Calendar cal = java.util.Calendar.getInstance();
|
|
|
cal.setTime(new Date());
|
|
cal.setTime(new Date());
|