yupeng
2025-03-13 96a7015065775e5c3bc3d6458b86b28ad7bfb46b
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(".")) );
            // 等待进程完成,设置超时
            if (!process.waitFor(120, TimeUnit.SECONDS)) {
                process.destroyForcibly();
                throw new RuntimeException("转换超时");
            }
            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");
            stream.close();
            inputStream.close();
            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;