java实现word转pdf

server/2024/12/14 17:41:45/

1、使用技术

linux:libreoffice
windows:dom4j

2、java代码

import com.documents4j.api.DocumentType;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.multipart.MultipartFile;import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.UUID;@Slf4j
public class WordToPdfUtils {private static String OS_NAME = "os.name";private static String WINDOWS = "windows";private static String DOCX = ".docx";private static String PDF = ".pdf";private static String TEMP_PATH = "/tmp";public static File wordToPdf(MultipartFile inputWord) {boolean IS_WINDOWS = System.getProperty(OS_NAME).toLowerCase().contains(WINDOWS);File tempWordFile = transferToFile(inputWord);File pdfFile;try {if (IS_WINDOWS) {pdfFile = new File(UUID.randomUUID() + PDF);winWordToPdf(pdfFile, tempWordFile);} else {pdfFile = linuxWordToPdf(TEMP_PATH, tempWordFile);}return pdfFile;} finally {if (tempWordFile.exists()) {tempWordFile.delete();}}}public static File wordToPdf(ByteArrayOutputStream outputStream) {boolean IS_WINDOWS = System.getProperty(OS_NAME).toLowerCase().contains(WINDOWS);File tempWordFile = outputStreamToFile(outputStream, UUID.randomUUID() + PDF);File pdfFile;try {if (IS_WINDOWS) {pdfFile = new File(UUID.randomUUID() + PDF);winWordToPdf(pdfFile, tempWordFile);} else {pdfFile = linuxWordToPdf(TEMP_PATH, tempWordFile);}return pdfFile;} finally {if (tempWordFile.exists()) {tempWordFile.delete();}}}public static File outputStreamToFile(OutputStream outputStream, String fileName) {File file = new File(fileName);try (OutputStream fileOutput = new FileOutputStream(file)) {// 将数据从ByteArrayOutputStream转移到文件输出流((ByteArrayOutputStream) outputStream).writeTo(fileOutput);return file;} catch (IOException e) {log.error("outputStreamToFile error", e);return null;}}public static MultipartFile convert(File file) throws IOException {FileInputStream fi = new FileInputStream(file);return new MockMultipartFile("file",file.getName(), null, fi);}/*** windows系统wordpdf** @param pdfFile  转换后的pdf文件* @param wordFile word源文件*/public static void winWordToPdf(File pdfFile, File wordFile) {IConverter converter = LocalConverter.builder().build();FileInputStream fileInputStream = null;FileOutputStream fileOutputStream = null;try {fileInputStream = new FileInputStream(wordFile);fileOutputStream = new FileOutputStream(pdfFile);converter.convert(fileInputStream).as(DocumentType.DOCX).to(fileOutputStream).as(DocumentType.PDF).execute();} catch (FileNotFoundException fileNotFoundException) {throw new ResultException(GlobalCodeEnum.WORD2PDF_ERROR, "文件不存在");} finally {if (fileInputStream != null) {try {fileInputStream.close();} catch (IOException e) {e.printStackTrace();}}if (fileOutputStream != null) {try {fileOutputStream.close();} catch (IOException e) {e.printStackTrace();}}}}/*** 创建具有唯一性的临时文件** @param originalFilename 原始文件名* @return 创建好的临时文件对象* @throws IOException 如果创建临时文件过程中出现IO异常*/private static File createUniqueTempFile(String originalFilename) throws IOException {String uniqueIdentifier = UUID.randomUUID().toString() + System.nanoTime();return File.createTempFile("temp-" + uniqueIdentifier + "-", "-" + originalFilename);}/*** 根据原始Word文件名生成对应的PDF文件名** @param wordFileName Word文件名* @return PDF文件名*/private static String getPdfFileName(String wordFileName) {return wordFileName.replaceFirst("[.][^.]+$", ".pdf");}/*** 设置PDF文件的HTTP响应头信息** @param response         HTTP响应对象* @param originalFilename 原始文件名*/private static void setPdfResponseHeaders(HttpServletResponse response, String originalFilename) {response.setContentType("application/pdf");response.setHeader("Content-Disposition", "attachment; filename=\"" + URLEncoder.encode(getPdfFileName(originalFilename)) + "\"");}/*** linux系统wordpdf* 使用LibreOffice转换。系统需安装LibreOffice* 转换命令 libreoffice --invisible --convert-to pdf --outdir output_dir source_path* 转换后的pdf文件名使用的是源文件的名称,所以如果要指定输出文件名称,就需把源文件名称改成想要输出的名称** @param wordFile word源文件*/public static File linuxWordToPdf(String outPutPath, File wordFile) {try {// 构建LibreOffice的下一行工具命令String command = "libreoffice --headless --invisible --convert-to pdf:writer_pdf_Export " + wordFile.getAbsolutePath() + "  --outdir " + outPutPath;log.info(command);// 执行转换命令if (executeLinuxCmd(command)) {return new File(outPutPath + File.separator + wordFile.getName().split("\\.")[0] + "." + wordFile.getName().split("\\.")[1]);}return null;} catch (Exception e) {log.error("linuxWordToPdf linux环境word转换为pdf时出现异常!", e);return null;}}/*** 执行命令行** @param command 命令行* @return*/private static boolean executeLinuxCmd(String command) throws IOException, InterruptedException {// 使用Java的ProcessBuilder来执行Linux命令ProcessBuilder processBuilder = new ProcessBuilder("/bin/bash", "-c", command);Process process = processBuilder.start();// 等待命令执行完成,并获取输出和错误流信息int exitCode = process.waitFor();if (exitCode != 0) {log.error("执行命令 {} 失败,退出码:{}", command, exitCode);return false;}return true;}private static File transferToFile(MultipartFile multipartFile) {String path = UUID.randomUUID() + DOCX;File file = new File(path);try {if (!file.exists()) {file.createNewFile();}FileCopyUtils.copy(multipartFile.getBytes(), file);} catch (Exception e) {throw new RuntimeException(e);}return file;}}

3、libreoffice

下载 LibreOffice | LibreOffice 简体中文官方网站 - 自由免费的办公套件

linux安装

#libreoffice的安装步骤#1.先将libreoffice的rpm文件上传至服务器
#2.将rpm压缩包解压到/opt目录下
tar -zxvf /tmp/LibreOffice_24.8.1_Linux_x86-64_rpm.tar.gz -C /opt/libreoffice
#3.进入解压目录
cd /opt/libreoffice/LibreOffice_24.8.1.2_Linux_x86-64_rpm/RPMS
#4.安装rpm包
yum localinstall *.rpm
#5.检查是否安装完成
libreoffice24.8 --version

dockerfile示例

FROM xxx/library/xxx-jdk17:1.0
USER 0
RUN mkdir -p /testdata/logs \
&& mkdir /usr/finance-lease \
&& ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtimeRUN cd /testdata && curl -O https://arthas.aliyun.com/arthas-boot.jar# 切换 Rocky Linux 的 dnf 源为阿里云镜像源
RUN sed -i 's|^mirrorlist=|#mirrorlist=|g' /etc/yum.repos.d/rocky.repo && \sed -i 's|^#baseurl=http://dl.rockylinux.org|baseurl=http://mirrors.cloud.aliyuncs.com|g' /etc/yum.repos.d/rocky.repo && \dnf clean all && dnf makecache# 判断是否为 Linux 系统,如果是则安装 LibreOffice
RUN if [ -f /etc/os-release ]; then \if [ -x /usr/bin/apt-get ]; then \apt-get update && apt-get install -y libreoffice; \elif [ -x /usr/bin/yum ]; then \yum update -y && yum install -y libreoffice; \elif [ -x /usr/bin/dnf ]; then \dnf update -y && dnf install -y libreoffice; \elif [ -x /usr/bin/zypper ]; then \zypper refresh && zypper install -y libreoffice; \elif [ -x /usr/bin/pacman ]; then \pacman -Syu --noconfirm libreoffice; \elif [ -x /usr/bin/apk ]; then \apk add --no-cache libreoffice; \else \echo "Unrecognized package manager, skipping LibreOffice installation"; \fi; \else \echo "Not a Linux-based system, skipping LibreOffice installation"; \fiCOPY ../entrypoint.sh /usr/finance-lease/entrypoint.sh
COPY ./finance-lease-business/target/financelease.jar /usr/finance-lease/financelease.jar
EXPOSE 8097
EXPOSE 10091
ENTRYPOINT ["/bin/bash", "/usr/finance-lease/entrypoint.sh"]

4、使用示例

             //获取文件输入流信息URL url = new URL(fileInfo.getOssFullPath());inputStream = url.openConnection().getInputStream();//注意不能直接使用XWPFDocument,会出现类型转换异常,直接使用子类MyXWPFDocument xwpfDocument = new MyXWPFDocument(inputStream);//填充合同模板变量值,生成合同文件WordExportUtil.exportWord07(xwpfDocument, templateParams);xwpfDocument.write(outputStream);//转为pdfFile file = WordToPdfUtils.wordToPdf(outputStream);


http://www.ppmy.cn/server/150143.html

相关文章

token失效重新存储发起请求

import axios from axios import { MessageBox, Message } from element-ui import store from /store import Router from /router import { getCookie, setToken, setCookie } from ./auth// 因为后端环境区分v1 v2 剔除测试盛传的环境配置,并添加统一前缀 const …

日常健康:点滴积累,守护生命活力

在现代社会的快节奏生活中,日常健康往往容易被忽视,然而,它却是我们享受美好生活、实现人生价值的基石。 饮食方面,注重营养均衡是关键。每日三餐应合理搭配,保证碳水化合物、蛋白质、脂肪、维生素和矿物质的充足摄入。…

Nginx反向代理与负载均衡应用实践

Nginx反向代理与负载均衡应用实践 1.1 集群简介 简单地说 ,集群就是指一组(若干个)相互独立的计算机 ,利用高速通信网络组成的一 个较大的计算机服务系统 ,每个集群节点(即集群中的每台计算机)…

Android 好的开源库

1. 权限请求框架 GitHub - getActivity/XXPermissions: Android 权限请求框架,已适配 Android 14 2. 下载框架 GitHub - lingochamp/okdownload: A Reliable, Flexible, Fast and Powerful download engine.

linux-16 关于shell(十五)date,clock,hwclock,man,时间管理,命令帮助

想显示一下当前系统上的时间该怎么显示?有一个命令叫做date,来看date命令,如下图, 第一个星期几对吧?然后是月日小时分钟秒,最后一个是年对吧?CST指的是它的时间格式,我这个可以先姑…

每天40分玩转Django:Django模板系统

Django模板系统 一、课程概述 学习项目具体内容预计用时模板语法变量、标签、过滤器、注释90分钟模板继承模板层级、块、包含60分钟静态文件配置、管理、使用90分钟 二、模板基础配置 2.1 模板配置 # settings.py TEMPLATES [{BACKEND: django.template.backends.django.D…

软包拆垛自动化:深度视觉与智能算法如何重塑行业格局?

在现代工业生产和物流场景中,自动化拆垛已成为提升效率和降低人工操作风险的关键环节。特别是在涉及软包、纸箱、麻包袋等不规则物体的行业,如塑胶粒子、化肥、食品加工等。 软包拆垛的行业挑战 软包、纸箱等不规则物体在堆垛时由于形状不规则、材质多…

UE5 C+、C++、C# 构造方法区别示例

我们对比一下UE C、C 、C#的构造方法&#xff1a; 1. UE4 C例子&#xff1a; // 声明和构造合并在一起static ConstructorHelpers::FObjectFinder<UTexture2D> CrosshairTexObj(TEXT("/Game/Path"));// 使用加载的资源UTexture2D* Texture CrosshairTexObj.…