New file |
| | |
| | | package com.ruoyi.web.controller.tool; |
| | | |
| | | import com.documents4j.api.DocumentType; |
| | | 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; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | 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 |
| | | public class PdfUtils { |
| | | @Autowired |
| | | private TencentCosUtil tencentCosUtil; |
| | | /** |
| | | * word 转 pdf |
| | | * |
| | | */ |
| | | // 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 { |
| | | // 确保路径正确性 |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | // 等待进程完成,设置超时 |
| | | 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"); |
| | | return s; |
| | | |
| | | } catch (Exception e) { |
| | | throw new RuntimeException("PDF转换失败: " + e.getMessage(), e); |
| | | } |
| | | } |
| | | |
| | | 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 { |
| | | // 创建一个临时文件 |
| | | File tempFile = File.createTempFile(fileName, ".pdf"); |
| | | |
| | | // 将ByteArrayOutputStream中的数据写入临时文件 |
| | | try (FileOutputStream fos = new FileOutputStream(tempFile)) { |
| | | baos.writeTo(fos); |
| | | } catch (IOException e) { |
| | | e.printStackTrace(); |
| | | } |
| | | |
| | | // 创建一个MultipartFile对象 |
| | | return new MockMultipartFile( |
| | | fileName + ".pdf", // 参数名称 |
| | | fileName + ".pdf", // 文件名 |
| | | "application/pdf", // 内容类型 |
| | | Files.readAllBytes(tempFile.toPath()) // 文件内容 |
| | | ); |
| | | } |
| | | |
| | | /** |
| | | * file转byte |
| | | */ |
| | | public static byte[] file2byte(File file){ |
| | | byte[] buffer = null; |
| | | try{ |
| | | FileInputStream fis = new FileInputStream(file); |
| | | ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| | | byte[] b = new byte[1024]; |
| | | int n; |
| | | while ((n = fis.read(b)) != -1) |
| | | { |
| | | bos.write(b, 0, n); |
| | | } |
| | | fis.close(); |
| | | bos.close(); |
| | | buffer = bos.toByteArray(); |
| | | }catch (FileNotFoundException e){ |
| | | e.printStackTrace(); |
| | | } |
| | | catch (IOException e){ |
| | | e.printStackTrace(); |
| | | } |
| | | return buffer; |
| | | } |
| | | |
| | | /** |
| | | * byte 转file |
| | | */ |
| | | public static File byte2File(byte[] buf, String filePath, String fileName){ |
| | | BufferedOutputStream bos = null; |
| | | FileOutputStream fos = null; |
| | | OutputStreamWriter osw = null; |
| | | File file = null; |
| | | try{ |
| | | File dir = new File(filePath+"/"); |
| | | if (!dir.exists()){ |
| | | dir.mkdirs(); |
| | | } |
| | | file = new File(filePath +File.separator + fileName); |
| | | fos = new FileOutputStream(file); |
| | | bos = new BufferedOutputStream(fos); |
| | | // osw = new OutputStreamWriter(fos, StandardCharsets.UTF_8); |
| | | bos.write(buf); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | finally{ |
| | | if (bos != null){ |
| | | try{ |
| | | bos.close(); |
| | | }catch (IOException e){ |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | if (fos != null){ |
| | | try{ |
| | | fos.close(); |
| | | }catch (IOException e){ |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | return file; |
| | | } |
| | | /** |
| | | * multipartFile转File |
| | | **/ |
| | | public static File multipartFile2File(MultipartFile multipartFile){ |
| | | File file = null; |
| | | if (multipartFile != null){ |
| | | try { |
| | | file= File.createTempFile("tmp", null); |
| | | multipartFile.transferTo(file); |
| | | System.gc(); |
| | | file.deleteOnExit(); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | log.warn("multipartFile转File发生异常:"+e); |
| | | } |
| | | } |
| | | return file; |
| | | } |
| | | |
| | | |
| | | public static void main(String[] args) { |
| | | // String url = "file:///E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09\\专业技术工作总结.docx"; |
| | | // String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09"; |
| | | // String fileName = "专业技术工作总结.docx"; |
| | | // String s = wordToPdf(url, filePath, fileName); |
| | | // System.err.println(s); |
| | | |
| | | // String url = "file:///F:\\测试动态列表Word.doc"; |
| | | //// String filePath = "E:\\qiyeweixin\\WXWork\\1688855207501340\\Cache\\File\\2024-09"; |
| | | //// String fileName = "专业技术工作总结.docx";4 |
| | | // String filePath = "F:\\"; |
| | | // |
| | | // String s = wordToPdf(url, filePath, "测试动态列表Word.doc"); |
| | | // System.err.println(s); |
| | | |
| | | |
| | | |
| | | // TODO Auto-generated method stub |
| | | |
| | | |
| | | // HashMap<String, Object> paramMap = new HashMap<>(); |
| | | // paramMap.put("CorpID", "SCZT006959"); |
| | | // paramMap.put("Pwd", "123456"); |
| | | // paramMap.put("Mobile", "19522115070"); |
| | | // paramMap.put("Cell", ""); |
| | | // paramMap.put("SendTime", ""); |
| | | // paramMap.put("Content", java.net.URLEncoder.encode("你好,这是测试短信发送。【职评网】")); |
| | | // String result3 = HttpUtil.post("http://sdk2.028lk.com/sdk2/BatchSend2.aspx", paramMap); |
| | | // if (result3 == null) { |
| | | // result3 = ""; |
| | | // } |
| | | // result3 = StrUtil.trim(result3); |
| | | // log.info("返回结果:" + result3); |
| | | // |
| | | // if (result3.matches("^\\d+$") && !result3.equals("0")) { |
| | | // return; |
| | | // } |
| | | |
| | | } |
| | | |
| | | public String test(String 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(filePath, fileName); |
| | | System.err.println(s); |
| | | |
| | | return s; |
| | | } |
| | | |
| | | } |