From 1fad0578c97abbb7fc30f59eb1de0f23f08ddde1 Mon Sep 17 00:00:00 2001
From: zhangmei <645025773@qq.com>
Date: 星期四, 27 三月 2025 15:21:15 +0800
Subject: [PATCH] 流水、开票营业部权限

---
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java |  247 +++++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 215 insertions(+), 32 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
index 71c5a6c..ba43f3f 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java
@@ -4,6 +4,7 @@
 import com.documents4j.api.IConverter;
 import com.documents4j.job.LocalConverter;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.poi.xwpf.usermodel.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.mock.web.MockMultipartFile;
 import org.springframework.stereotype.Component;
@@ -11,7 +12,13 @@
 
 import java.io.*;
 import java.net.URL;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
 
 @Slf4j
 @Component
@@ -21,47 +28,223 @@
     /**
      * word 转 pdf
      *
-     * @param url
      */
-    public  String wordToPdf(String url,String filePath, String fileName) {
+//    public  String wordToPdf(String url,String filePath, String fileName) {
+//        try {
+//            DocumentType documentType = DocumentType.DOC;
+//            if(url.contains(".docx")){
+//                documentType = DocumentType.DOCX;
+//            }
+//            if(url.contains(".doc")){
+//                documentType = DocumentType.DOC;
+//            }
+//            if(url.contains(".xlsx")){
+//                documentType = DocumentType.XLSX;
+//            }else {
+//                if(url.contains(".xls")){
+//                    documentType = DocumentType.XLS;
+//                }
+//            }
+//            InputStream inputStream = new URL(url).openStream();
+//            ByteArrayOutputStream stream = new ByteArrayOutputStream();
+//            IConverter converter = LocalConverter.builder().build();
+//            converter.convert(inputStream)
+//                    .as(documentType)
+//                    .to(stream)
+//                    .as(DocumentType.PDF).execute();
+//
+//            //上传图片
+//            byte2File(stream.toByteArray(),filePath + "/pdf",fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf");
+//            MultipartFile multipartFile = convertToMultipartFile(stream,fileName.substring(0,fileName.lastIndexOf(".")) );
+//            String s = tencentCosUtil.upLoadFile(multipartFile,"/wordToPdf");
+//
+//            stream.close();
+//            inputStream.close();
+//            return s;
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//        return null;
+//    }
+
+    public String wordToPdf(String filePath, String fileName) {
         try {
-            DocumentType documentType = DocumentType.DOC;
-            if(url.contains(".docx")){
-                documentType = DocumentType.DOCX;
-            }
-            if(url.contains(".doc")){
-                documentType = DocumentType.DOC;
-            }
-            if(url.contains(".xlsx")){
-                documentType = DocumentType.XLSX;
-            }else {
-                if(url.contains(".xls")){
-                    documentType = DocumentType.XLS;
+            // 确保路径正确性
+            String inputFile = new File(filePath, fileName).getAbsolutePath();
+            String outputDir = new File(filePath, "pdf").getAbsolutePath();
+
+            // 创建输出目录
+            new File(outputDir).mkdirs();
+
+            // 使用完整的转换参数
+            List<String> command = Arrays.asList(
+                    "/usr/bin/libreoffice",  // 使用完整路径
+                    "--headless",
+                    "--norestore",
+                    "--convert-to",
+                    "pdf:writer_pdf_Export:PDFExport{" +
+                            "EmbedStandardFonts=1;" +
+                            "EmbedFonts=1;" +
+                            "EmbedOnlyUsedFonts=0;" +
+                            "UseTaggedPDF=1" +
+                            "}",
+                    "--outdir",
+                    outputDir,
+                    inputFile
+            );
+
+            // 创建进程构建器
+            ProcessBuilder pb = new ProcessBuilder(command);
+
+            // 设置环境变量
+            Map<String, String> env = pb.environment();
+            env.put("LC_ALL", "zh_CN.UTF-8");
+            env.put("LANG", "zh_CN.UTF-8");
+            env.put("LANGUAGE", "zh_CN.UTF-8");
+
+            // 重定向错误流到标准输出
+            pb.redirectErrorStream(true);
+
+            // 启动进程
+            Process process = pb.start();
+
+            // 读取输出
+            StringBuilder output = new StringBuilder();
+            try (BufferedReader reader = new BufferedReader(
+                    new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8))) {
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    output.append(line).append("\n");
+                    System.out.println(line);
                 }
             }
-            InputStream inputStream = new URL(url).openStream();
-            ByteArrayOutputStream stream = new ByteArrayOutputStream();
-            IConverter converter = LocalConverter.builder().build();
-            converter.convert(inputStream)
-                    .as(documentType)
-                    .to(stream)
-                    .as(DocumentType.PDF).execute();
 
-            //上传图片
-            byte2File(stream.toByteArray(),filePath + "/pdf",fileName.substring(0,fileName.lastIndexOf(".")) + ".pdf");
-            MultipartFile multipartFile = convertToMultipartFile(stream,fileName.substring(0,fileName.lastIndexOf(".")) );
-            String s = tencentCosUtil.upLoadFile(multipartFile);
+            // 等待进程完成,设置超时
+            if (!process.waitFor(120, TimeUnit.SECONDS)) {
+                process.destroyForcibly();
+                throw new RuntimeException("转换超时");
+            }
 
-            stream.close();
-            inputStream.close();
+            int exitCode = process.exitValue();
+            if (exitCode != 0) {
+                throw new RuntimeException("转换失败,退出码:" + exitCode + "\n输出:" + output);
+            }
+
+            // 检查生成的PDF文件
+            String pdfFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
+            File pdfFile = new File(outputDir, pdfFileName);
+
+            if (!pdfFile.exists() || pdfFile.length() == 0) {
+                throw new RuntimeException("PDF文件未生成或为空");
+            }
+            String absolutePath = pdfFile.getAbsolutePath();
+
+            MultipartFile multipartFile = convertFileToMultipartFile(pdfFile);
+            String s = tencentCosUtil.upLoadFile(multipartFile,"/wordToPdf");
             return s;
+
         } catch (Exception e) {
-            e.printStackTrace();
+            throw new RuntimeException("PDF转换失败: " + e.getMessage(), e);
         }
-        return null;
     }
 
+    public MultipartFile convertFileToMultipartFile(File file) throws IOException {
+        // 读取文件内容到字节数组
+        byte[] fileContent = Files.readAllBytes(file.toPath());
 
+        // 创建 MultipartFile 对象
+        MultipartFile multipartFile = new MockMultipartFile(
+                file.getName(),       // 文件名
+                file.getName(),       // 原始文件名
+                "application/pdf",  // 内容类型,根据实际情况调整
+                fileContent           // 文件内容
+        );
+
+        return multipartFile;
+    }
+
+    // 在使用前检查和配置环境
+    public static void setupEnvironment() {
+        try {
+            // 1. 检查LibreOffice安装
+            checkLibreOffice();
+
+            // 2. 检查和安装字体
+            installFonts();
+
+            // 3. 配置字体
+            configureFonts();
+
+            // 4. 验证环境变量
+            checkEnvironment();
+
+        } catch (Exception e) {
+            throw new RuntimeException("环境设置失败: " + e.getMessage(), e);
+        }
+    }
+
+    private static void checkLibreOffice() throws IOException, InterruptedException {
+        Process process = Runtime.getRuntime().exec("which libreoffice");
+        if (process.waitFor() != 0) {
+            throw new RuntimeException("LibreOffice未安装");
+        }
+    }
+
+    private static void installFonts() throws IOException, InterruptedException {
+        // 创建字体安装脚本
+        String scriptContent =
+                "#!/bin/bash\n" +
+                        "apt-get update\n" +
+                        "apt-get install -y fonts-wqy-zenhei fonts-wqy-microhei fonts-arphic-ukai fonts-arphic-uming\n" +
+                        "fc-cache -fv\n";
+
+        File script = new File("/tmp/install_fonts.sh");
+        Files.write(script.toPath(), scriptContent.getBytes());
+        script.setExecutable(true);
+
+        // 执行脚本
+        Process process = Runtime.getRuntime().exec("sudo /tmp/install_fonts.sh");
+        process.waitFor();
+
+        // 清理脚本
+        script.delete();
+    }
+
+    private static void configureFonts() throws IOException {
+        // 创建字体配置文件
+        String fontConfig =
+                "<?xml version=\"1.0\"?>\n" +
+                        "<!DOCTYPE fontconfig SYSTEM \"fonts.dtd\">\n" +
+                        "<fontconfig>\n" +
+                        "  <match target=\"pattern\">\n" +
+                        "    <test name=\"family\"><string>serif</string></test>\n" +
+                        "    <edit name=\"family\" mode=\"prepend\">\n" +
+                        "      <string>WenQuanYi Zen Hei</string>\n" +
+                        "    </edit>\n" +
+                        "  </match>\n" +
+                        "  <match target=\"pattern\">\n" +
+                        "    <test name=\"family\"><string>sans-serif</string></test>\n" +
+                        "    <edit name=\"family\" mode=\"prepend\">\n" +
+                        "      <string>WenQuanYi Zen Hei</string>\n" +
+                        "    </edit>\n" +
+                        "  </match>\n" +
+                        "</fontconfig>";
+
+        // 写入配置文件
+        File configFile = new File(System.getProperty("user.home") + "/.fonts.conf");
+        Files.write(configFile.toPath(), fontConfig.getBytes());
+    }
+
+    private static void checkEnvironment() {
+        // 检查环境变量
+        String[] requiredVars = {"LANG", "LC_ALL", "LANGUAGE"};
+        for (String var : requiredVars) {
+            String value = System.getenv(var);
+            if (value == null || !value.contains("zh_CN")) {
+                System.err.println("警告: " + var + " 环境变量未正确设置");
+            }
+        }
+    }
 
     public static MultipartFile convertToMultipartFile(ByteArrayOutputStream baos, String fileName) throws IOException {
         // 创建一个临时文件
@@ -209,12 +392,12 @@
     }
 
     public String test(String fileName){
-        String url = "file:///E:\\"+fileName;
+//        String url = "file:///usr/local/project/file/"+fileName;
 //        String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09";
 //        String fileName = "专业技术工作总结.docx";4
-        String filePath = "E:\\";
+        String filePath = "/usr/local/project/file/";
 
-        String s = wordToPdf(url, filePath, fileName);
+        String s = wordToPdf(filePath, fileName);
         System.err.println(s);
 
         return s;

--
Gitblit v1.7.1