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;
|
}
|
|
}
|