xiahan 1 місяць тому
батько
коміт
2d34776697

+ 62 - 22
qhse-common/src/main/java/com/rongwei/bscommon/sys/service/impl/FileFormatConversionServiceImpl.java

@@ -1,11 +1,12 @@
 package com.rongwei.bscommon.sys.service.impl;
 
+import com.aspose.cells.LoadFormat;
+import com.aspose.cells.LoadOptions;
+import com.aspose.cells.PdfSaveOptions;
 import com.aspose.cells.*;
-import com.aspose.pdf.FontRepository;
-import com.aspose.pdf.Page;
-import com.aspose.pdf.TextStamp;
-import com.aspose.pdf.TextState;
+import com.aspose.pdf.*;
 import com.aspose.words.Document;
+import com.aspose.words.FontSettings;
 import com.aspose.words.SaveOptions;
 import com.rongwei.bscommon.sys.service.FileFormatConversionService;
 import com.rongwei.bscommon.sys.utils.AsposeLicenseConfig;
@@ -22,9 +23,9 @@ import org.springframework.stereotype.Service;
 
 import javax.imageio.ImageIO;
 import javax.servlet.http.HttpServletResponse;
-import java.awt.*;
 import java.awt.Color;
 import java.awt.Font;
+import java.awt.*;
 import java.awt.image.BufferedImage;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -47,6 +48,7 @@ import static com.rongwei.bscommon.sys.utils.QHSEConstant.FileType.*;
 @Service
 public class FileFormatConversionServiceImpl implements FileFormatConversionService {
     private static final Logger log = LoggerFactory.getLogger(FileFormatConversionServiceImpl.class);
+
     @Autowired
     private SysFileItemServiceImpl sysFileItemServiceImpl;
 
@@ -82,7 +84,7 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
         try {
             fileName = URLEncoder.encode(sysFileItemDo.getFilename(), "utf-8");
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new CustomException("文件名转换失败!请联系系统管理员");
         }
 
         response.setHeader("Content-Disposition", "inline; filename=" + fileName);
@@ -92,8 +94,8 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
             SysUserVo currentUser = QHSEUtils.getCurrentUser();
             waterMarkStr = String.format(DEFAULT_WATER_MARK, currentUser.getAccount(), currentUser.getName());
         }
-
-
+        FontSettings fontSettings = new FontSettings();
+        fontSettings.setFontsFolder("/usr/share/fonts/simsun.ttc", true); // 指定中文字体目录
         if (XLSX.equals(lowerCaseFileTYpe) || XLS.equals(lowerCaseFileTYpe)) {
             response.setContentType(QHSEConstant.ContentType.PDF);
             AsposeLicenseConfig.getExcelLicense();
@@ -105,14 +107,14 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
             response.setContentType(QHSEConstant.ContentType.PDF);
             pdfDispose(fullpath, response, waterMark, waterMarkStr);
         } else if ((PNG.equals(lowerCaseFileTYpe) || JPEG.equals(lowerCaseFileTYpe) || JPG.equals(lowerCaseFileTYpe)) && waterMark) {
-            pictureDispose(fullpath, response, waterMarkStr,lowerCaseFileTYpe);
+            pictureDispose(fullpath, response, waterMarkStr, lowerCaseFileTYpe);
         } else {
             try {
                 response.setContentType(STREAM);
                 Files.copy(Paths.get(fullpath), response.getOutputStream());
             } catch (Exception e) {
                 log.error("文件名:{}格式化失败- 原因: {} | 异常类型: {}", sysFileItemDo.getFilename(), e.getMessage(), e.getClass().getSimpleName(), e);
-                throw new RuntimeException("获取预览文件失败!请联系系统管理员");
+                throw new CustomException("获取预览文件失败!请联系系统管理员");
             }
 
         }
@@ -154,8 +156,8 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
             g2d.setFont(font);
             g2d.setColor(Color.lightGray);
             // 循环平铺水印
-            for (int x = 0; x < newImage.getWidth() ; x += 200) {
-                for (int y = 0; y < newImage.getHeight() ; y += 100) {
+            for (int x = 0; x < newImage.getWidth(); x += 200) {
+                for (int y = 0; y < newImage.getHeight(); y += 100) {
                     // 设置旋转中心点
                     g2d.rotate(Math.toRadians(-45), x, y);
                     g2d.drawString(waterMarkStr, x, y);
@@ -183,7 +185,7 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
             }
         } catch (Exception e) {
             log.error("图片处理失败", e);
-            throw new RuntimeException("文件处理异常");
+            throw new CustomException("文件处理异常");
         }
     }
 
@@ -198,16 +200,32 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
     public void pdfDispose(String fullPath, HttpServletResponse response, boolean waterMark, String waterMarkStr) {
         try (OutputStream out = response.getOutputStream();
              InputStream templateStream = Files.newInputStream(Paths.get(fullPath))) {
+
             com.aspose.pdf.Document pdfDoc = new com.aspose.pdf.Document(templateStream);
+            // // 配置文本提取选项(解决字体问题)
+            // TextExtractionOptions options = new TextExtractionOptions(TextExtractionOptions.TextFormattingMode.Pure);
+            // // 使用 TextAbsorber 提取文本(支持复杂布局)
+            // TextAbsorber textAbsorber = new TextAbsorber(options);
+            // pdfDoc.getPages().accept(textAbsorber);
+            // TextFragmentAbsorber absorber = new TextFragmentAbsorber();
+            // // 替换缺失字体的文本片段
+            // for (TextFragment textFragment : absorber.getTextFragments()) {
+            //     textFragment.getTextState().setFont(FontRepository.findFont("Arial"));
+            // }
+            // // 获取完整文本
+            // String extractedText = textAbsorber.getText();
+            // log.error("提取到的完整文本:{}", extractedText);
             if (waterMark) {
                 addTextWatermark(pdfDoc, waterMarkStr, 0.5f);
             }
+            com.aspose.pdf.PdfSaveOptions saveOptions = new com.aspose.pdf.PdfSaveOptions();
+            pdfDoc.setEmbedStandardFonts(true);
             // 转换为 PDF 并输出到流
-            pdfDoc.save(out);
+            pdfDoc.save(out, saveOptions);
             out.flush();
         } catch (Exception e) {
             log.error("pdf预览失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-            throw new RuntimeException("获取预览文件失败!请联系系统管理员");
+            throw new CustomException("获取预览文件失败!请联系系统管理员");
         }
     }
 
@@ -249,7 +267,7 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
                 }
             } catch (Exception e) {
                 log.error("Excel转PDF失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-                throw new RuntimeException("文件转换失败,请联系系统管理员");
+                throw new CustomException("文件转换失败,请联系系统管理员");
             }
 
         } else {
@@ -272,7 +290,7 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
                 out.flush();
             } catch (Exception e) {
                 log.error("excel转pdf失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-                throw new RuntimeException("获取预览文件失败!请联系系统管理员");
+                throw new CustomException("获取预览文件失败!请联系系统管理员");
             }
         }
 
@@ -286,6 +304,8 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
      * @param opacity
      */
     private void addTextWatermark(com.aspose.pdf.Document pdfDoc, String watermarkText, float opacity) {
+
+
         for (Page page : pdfDoc.getPages()) {
             // 获取页面实际尺寸(排除边距)
             double width = page.getMediaBox().getWidth();
@@ -300,7 +320,7 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
             TextState textState = new TextState();
             textState.setFontSize(fontSize);
             textState.setForegroundColor(com.aspose.pdf.Color.getLightGray());
-            textState.setFont(FontRepository.findFont("Microsoft YaHei"));
+            textState.setFont(getDefaultFont());
 
             // 平铺水印
             for (double x = -100; x < width; x += spacing) {
@@ -340,12 +360,14 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
                 try (com.aspose.pdf.Document pdfDoc = new com.aspose.pdf.Document(new ByteArrayInputStream(excelPdfStream.toByteArray()))) {
                     addTextWatermark(pdfDoc, waterMarkStr, 0.5f);
                     // 3. 输出最终PDF
-                    pdfDoc.save(out);
+                    com.aspose.pdf.PdfSaveOptions saveOptions = new com.aspose.pdf.PdfSaveOptions();
+                    saveOptions.setDefaultFontName("YaHei");
+                    pdfDoc.save(out, saveOptions);
                     out.flush();
                 }
             } catch (Exception e) {
                 log.error("Excel转PDF失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-                throw new RuntimeException("文件转换失败,请联系系统管理员");
+                throw new CustomException("文件转换失败,请联系系统管理员");
             }
 
         } else {
@@ -355,15 +377,33 @@ public class FileFormatConversionServiceImpl implements FileFormatConversionServ
                 // 设置 PDF 转换选项
                 PdfSaveOptions options = new PdfSaveOptions();
                 options.setCompliance(PdfCompliance.PDF_A_1_A); // 设置PDF/A-1a标准
-                // 3. 直接输出到响应流(避免中间文件)
                 doc.save(out, com.aspose.words.SaveFormat.PDF);
                 // 4. 强制刷新缓冲区(确保数据完整传输)
                 out.flush();
             } catch (Exception e) {
                 log.error("word转pdf失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-                throw new RuntimeException("获取预览文件失败!请联系系统管理员");
+                throw new CustomException("获取预览文件失败!请联系系统管理员");
             }
         }
     }
 
+    public com.aspose.pdf.Font getDefaultFont() {
+        // 1. 加载字体(优先使用文件路径方式)
+        com.aspose.pdf.Font defaultFont = null;
+        try {
+            // 尝试直接加载字体文件(最可靠的方式)
+            defaultFont = FontRepository.openFont("/usr/share/fonts/msyh.ttc"); // Linux 字体路径
+        } catch (Exception e) {
+            try {
+                // 备选方案:尝试通过名称查找
+                defaultFont = FontRepository.findFont("Microsoft YaHei");
+            } catch (Exception ex) {
+                // 最终回退到系统默认中文字体
+                defaultFont = FontRepository.findFont("Noto Sans CJK SC"); // Linux 常用开源字体
+            }
+        }
+
+        return defaultFont;
+    }
+
 }

+ 10 - 10
qhse-common/src/main/java/com/rongwei/bscommon/sys/service/impl/QhseTargetResponsibilityDocumentServiceImpl.java

@@ -88,24 +88,24 @@ public class QhseTargetResponsibilityDocumentServiceImpl extends ServiceImpl<Qhs
         SysFileItemDo tempDo = fileFormatConversionService.fileCheck(fileId);
         if (tempDo == null) {
             log.error("无法根据id:{}获取到责任书文件信息", fileId);
-            throw new RuntimeException("无法获取到责任书");
+            throw new CustomException("无法获取到责任书");
         }
         // 模板路径
         String tempFullpath = tempDo.getFullpath();
         if (StringUtils.isBlank(tempFullpath)) {
             log.error("无法根据id:{}获取到责任书文件信息", fileId);
-            throw new RuntimeException("无法获取到责任书");
+            throw new CustomException("无法获取到责任书");
         }
         SysFileItemDo signatureDo = fileFormatConversionService.fileCheck(signatureId);
         if (signatureDo == null) {
             log.error("无法根据id:{}获取到签名信息", signatureId);
-            throw new RuntimeException("无法获取到签名");
+            throw new CustomException("无法获取到签名");
         }
         // 乙方签名路径
         String signaturePath = signatureDo.getFullpath();
         if (StringUtils.isBlank(signaturePath)) {
             log.error("无法根据id:{}获取到签名信息", signatureId);
-            throw new RuntimeException("无法获取到签名");
+            throw new CustomException("无法获取到签名");
         }
 
         String filetype = tempDo.getFiletype();
@@ -128,7 +128,7 @@ public class QhseTargetResponsibilityDocumentServiceImpl extends ServiceImpl<Qhs
             try {
                 fileName = URLEncoder.encode(tempDo.getFilename(), "utf-8");
             } catch (Exception e) {
-                throw new RuntimeException(e);
+                throw new CustomException("文件名转换异常");
             }
             response.setContentType("application/pdf");
             response.setHeader("Content-Disposition", "inline; filename=" + fileName);
@@ -143,7 +143,7 @@ public class QhseTargetResponsibilityDocumentServiceImpl extends ServiceImpl<Qhs
             out.flush();
         } catch (Exception e) {
             log.error("excel转pdf失败- 原因: {} | 异常类型: {}", e.getMessage(), e.getClass().getSimpleName(), e);
-            throw new RuntimeException("获取签名责任书失败!请联系系统管理员");
+            throw new CustomException("获取签名责任书失败!请联系系统管理员");
         }
     }
 
@@ -187,19 +187,19 @@ public class QhseTargetResponsibilityDocumentServiceImpl extends ServiceImpl<Qhs
                         .eq(BaseDo::getDeleted, "0"));
 
         boolean noSignatureData = documentSignatureDo.stream().anyMatch(info -> StringUtils.isNotBlank(info.getSignature()));
-        if (noSignatureData) {
+        if (!noSignatureData) {
             throw new CustomException("目标责任书未含甲方及乙方的签名,无法下载!");
         }
 
         Map<String, String> signatureDataMap = documentSignatureDo.stream().filter(info -> StringUtils.isNotBlank(info.getSignature())).collect(Collectors.groupingBy(QhseTargetResponsibilityDocumentSignatureDo::getSignaturesource,
                 Collectors.mapping(info -> {
                     String signature = info.getSignature();
-                    if (StringUtils.isNotBlank(signature)) {
+                    if (StringUtils.isBlank(signature)) {
                         return null; // 后面需要过滤掉null
                     }
                     // 使用"-;-"分割,取第一个部分
                     String[] parts = signature.split(FILE_SEPARATOR, 2); // 限制分割成2部分,这样性能更好,我们只需要第一部分
-                    return parts[0].trim(); // 取第一个部分并去除空格
+                    return parts[1].trim(); // 取第一个部分并去除空格
                 }, Collectors.joining(","))));
         // 甲方签名路径
         String partAPath = "";
@@ -242,7 +242,7 @@ public class QhseTargetResponsibilityDocumentServiceImpl extends ServiceImpl<Qhs
         try {
             fileName = URLEncoder.encode(value + docName + ".zip", "utf-8");
         } catch (Exception e) {
-            throw new RuntimeException(e);
+            throw new CustomException("文件名转换异常");
         }
         response.setContentType("application/zip");
         response.setHeader("Content-Disposition", "attachment; filename=" + fileName);

+ 4 - 0
qhse-server/src/main/java/com/rongwei/BusinessServerApplication.java

@@ -1,5 +1,7 @@
 package com.rongwei;
 
+import com.aspose.pdf.FolderFontSource;
+import com.aspose.pdf.FontRepository;
 import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -17,5 +19,7 @@ import org.springframework.scheduling.annotation.EnableScheduling;
 public class BusinessServerApplication {
     public static void main(String[] args) {
         SpringApplication.run(BusinessServerApplication.class, args);
+        FontRepository.getSources().add(new FolderFontSource("/usr/share/fonts"));
+        FontRepository.getSources().add(new FolderFontSource("/usr/share/fonts/ZH"));
     }
 }