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.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 {
|
// 1. 首先确保输入文件是UTF-8编码
|
String inputFile = filePath + fileName;
|
String outputDir = filePath + "/pdf";
|
String outputFileName = fileName.substring(0, fileName.lastIndexOf(".")) + ".pdf";
|
|
// 2. 创建临时文件用于转换
|
String tempDocx = createTempFileWithEncoding(inputFile);
|
|
// 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();
|
|
// 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");
|
}
|
}
|
|
// 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) {
|
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 {
|
// 创建一个临时文件
|
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;
|
}
|
|
}
|