From 40158f61b8bf3f07c3ebc928ccd8e5ccbc2e22ff Mon Sep 17 00:00:00 2001 From: 无关风月 <443237572@qq.com> Date: 星期四, 06 三月 2025 19:22:55 +0800 Subject: [PATCH] Merge branch 'master' of https://gitee.com/xiaochen991015/xizang --- ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/PdfUtils.java | 218 +++++++++++++++++++++++++++++++++++++++++++++-------- 1 files changed, 183 insertions(+), 35 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 9c274d7..172bfd6 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,11 @@ import java.io.*; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import java.util.concurrent.TimeUnit; @Slf4j @@ -22,7 +27,6 @@ /** * word 转 pdf * - * @param url */ // public String wordToPdf(String url,String filePath, String fileName) { // try { @@ -62,48 +66,192 @@ // return null; // } - public String wordToPdf(String url, String filePath, String fileName) { + public String wordToPdf(String filePath, String fileName) { try { - DocumentType documentType = DocumentType.DOC; - if (url.contains(".docx")) { - documentType = DocumentType.DOCX; - } else if (url.contains(".doc")) { - documentType = DocumentType.DOC; - } else if (url.contains(".xlsx")) { - documentType = DocumentType.XLSX; - } else if (url.contains(".xls")) { - documentType = DocumentType.XLS; - } + // 1. 首先确保输入文件是UTF-8编码 + String inputFile = filePath + fileName; + String outputDir = filePath + "/pdf"; + String outputFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf"; - // Ensure the URL has a protocol part - if (!url.startsWith("file://") && !url.startsWith("http://") && !url.startsWith("https://")) { - url = "file://" + url; - } + // 2. 创建临时文件用于转换 + String tempDocx = createTempFileWithEncoding(inputFile); - // 使用LibreOffice进行转换 - ProcessBuilder pb = new ProcessBuilder( - "soffice", - "--headless", - "--convert-to", "pdf", - "--outdir", new File(filePath+ "/pdf"+fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf").getParent(), - filePath+fileName - ); + // 3. 使用更详细的LibreOffice转换参数 + List<String> command = new ArrayList<>(); + command.add("/usr/bin/soffice"); + command.add("--headless"); + command.add("--convert-to"); + command.add("pdf:writer_pdf_Export:PDFExport{'EmbedStandardFonts':true}"); + command.add("--outdir"); + command.add(outputDir); + command.add(tempDocx); + + ProcessBuilder pb = new ProcessBuilder(command); + + // 4. 设置更完整的环境变量 + 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"); + env.put("PYTHONIOENCODING", "utf8"); + env.put("JAVA_TOOL_OPTIONS", "-Dfile.encoding=UTF-8"); + + // 5. 执行转换 Process process = pb.start(); - // 等待转换完成 - int exitCode = process.waitFor(); - if (exitCode == 0) { - System.out.println("PDF转换成功!"); - } else { - System.out.println("PDF转换失败!"); + // 6. 读取输出 + 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"); + } } - return ""; + + // 7. 等待进程完成 + int exitCode = process.waitFor(); + + // 8. 清理临时文件 + new File(tempDocx).delete(); + + if (exitCode == 0) { + return outputDir + "/" + outputFileName; + } else { + throw new RuntimeException("转换失败: " + output.toString()); + } + } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("Failed to generate PDF: " + e.getMessage(), e); + throw new RuntimeException("PDF转换失败: " + e.getMessage(), e); + } + } + private static String createTempFileWithEncoding(String inputFile) { + try { + // 1. 读取原始文档 + XWPFDocument doc = new XWPFDocument(new FileInputStream(inputFile)); + + // 2. 修改文档字体和编码 + for (XWPFParagraph paragraph : doc.getParagraphs()) { + for (XWPFRun run : paragraph.getRuns()) { + // 设置中文字体 + run.setFontFamily("WenQuanYi Zen Hei"); + run.setFontFamily("WenQuanYi Zen Hei", XWPFRun.FontCharRange.eastAsia); + + // 确保文本是UTF-8编码 + String text = run.getText(0); + if (text != null) { + text = new String(text.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + run.setText(text, 0); + } + } + } + + // 3. 处理表格中的文本 + for (XWPFTable table : doc.getTables()) { + for (XWPFTableRow row : table.getRows()) { + for (XWPFTableCell cell : row.getTableCells()) { + for (XWPFParagraph paragraph : cell.getParagraphs()) { + for (XWPFRun run : paragraph.getRuns()) { + run.setFontFamily("WenQuanYi Zen Hei"); + run.setFontFamily("WenQuanYi Zen Hei", XWPFRun.FontCharRange.eastAsia); + + String text = run.getText(0); + if (text != null) { + text = new String(text.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8); + run.setText(text, 0); + } + } + } + } + } + } + + // 4. 保存为临时文件 + String tempFile = inputFile + ".temp.docx"; + try (FileOutputStream out = new FileOutputStream(tempFile)) { + doc.write(out); + } + + return tempFile; + + } catch (Exception e) { + throw new RuntimeException("处理文档编码失败: " + e.getMessage(), e); } } + // 在转换之前执行的环境检查 + private static void preConversionCheck() { + try { + // 1. 检查并安装必要的字体 + installRequiredFonts(); + + // 2. 验证LibreOffice安装 + verifyLibreOfficeInstallation(); + + // 3. 设置字体配置 + setupFontConfig(); + + } catch (Exception e) { + throw new RuntimeException("环境检查失败: " + e.getMessage(), e); + } + } + + private static void installRequiredFonts() { + try { + ProcessBuilder pb = new ProcessBuilder( + "sudo", "apt-get", "install", "-y", + "fonts-wqy-zenhei", + "fonts-wqy-microhei", + "fonts-arphic-ukai", + "fonts-arphic-uming" + ); + pb.inheritIO(); + Process p = pb.start(); + p.waitFor(); + } catch (Exception e) { + System.err.println("警告: 安装字体失败 - " + e.getMessage()); + } + } + + private static void verifyLibreOfficeInstallation() { + try { + Process p = Runtime.getRuntime().exec("soffice --version"); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(p.getInputStream()))) { + String version = reader.readLine(); + if (version == null || !version.contains("LibreOffice")) { + throw new RuntimeException("LibreOffice未正确安装"); + } + } + } catch (Exception e) { + throw new RuntimeException("LibreOffice检查失败: " + e.getMessage()); + } + } + + private static void setupFontConfig() { + try { + String fontConfig = + "<?xml version='1.0'?>\n" + + "<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>\n" + + "<fontconfig>\n" + + " <match target=\"pattern\">\n" + + " <test name=\"family\"><string>SimSun</string></test>\n" + + " <edit name=\"family\" mode=\"assign\" binding=\"same\">\n" + + " <string>WenQuanYi Zen Hei</string>\n" + + " </edit>\n" + + " </match>\n" + + "</fontconfig>"; + + String userHome = System.getProperty("user.home"); + File fontConfigFile = new File(userHome + "/.fonts.conf"); + + try (FileWriter writer = new FileWriter(fontConfigFile)) { + writer.write(fontConfig); + } + } catch (Exception e) { + System.err.println("警告: 设置字体配置失败 - " + e.getMessage()); + } + } public static MultipartFile convertToMultipartFile(ByteArrayOutputStream baos, String fileName) throws IOException { // 创建一个临时文件 @@ -251,12 +399,12 @@ } public String test(String fileName){ - String url = "file:///usr/local/project/file/"+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 = "/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