实现将docx转成PDF

最近实现了一个将docx转成PDF的功能,这里来记录一下实现过程

我是参考这篇文章Java将Word转换成PDF的常用用法_java_脚本之家

实现步骤基本上是按照上面文档中描述的内容,把大象装冰箱一共就三步

1、导入依赖

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>wordToPDF</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.4.RELEASE</version>
    </parent>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-log4j2</artifactId>
        </dependency>

        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.3.5</version>
            <scope>compile</scope>
        </dependency>

        <!--lombok-->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.6</version>
        </dependency>

        <!--word转换为PDF文档-->
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-local</artifactId>
            <version>1.0.3</version>
        </dependency>
        <dependency>
            <groupId>com.documents4j</groupId>
            <artifactId>documents4j-transformer-msoffice-word</artifactId>
            <version>1.0.3</version>
        </dependency>

    </dependencies>

</project>

2、增加日志的配置文件(这一步可以忽略)

application.yml

XML 复制代码
logging:
  config: classpath:log4j2.xml

log4j2.xml

XML 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration status="INFO" monitorInterval="30">
    <Properties>
        <property name="ALL_LOG_FILE_NAME">
            log/
        </property>
        <!-- 输出日志的格式 -->
        <property name="PATTERN">[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%M-%t] [%-5level] %logger{36}:%L - %msg%n</property>
    </Properties>
    <Appenders>
        <!--这个输出控制台的配置 -->
        <Console name="Console" target="SYSTEM_OUT">
            <!-- 控制台只输出level及以上级别的信息(onMatch),其他的直接拒绝(onMismatch) -->
            <ThresholdFilter level="trace" onMatch="ACCEPT" onMismatch="DENY"/>

            <PatternLayout pattern="${PATTERN}"/>
        </Console>
        <RollingFile name="RollingFileAll"
                     fileName="${ALL_LOG_FILE_NAME}/all.log"
                     filePattern="${ALL_LOG_FILE_NAME}/all-%d{yyyy-MM-dd}-%i.log">
            <Filters>
                <!--设置只输出级别为info的日志-->
                <ThresholdFilter level="all"/>
            </Filters>
            <!--文件输出格式-->
            <PatternLayout pattern="${PATTERN}"/>
            <Policies>
                <!--每天一个文件-->
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <!--单个文件的大小-->
                <SizeBasedTriggeringPolicy size="100 MB"/>
            </Policies>
            <!--设置保留的文件数据-->
            <DefaultRolloverStrategy max="12">
                <!--删除的规则-->
                <Delete basePath="${ALL_LOG_FILE_NAME}" maxDepth="2">
                    <!--保存文件名-->
                    <IfFileName glob="all-*.log"/>
                    <!--保留天数-->
                    <IfLastModified age="30d"/>
                </Delete>
            </DefaultRolloverStrategy>
        </RollingFile>

    </Appenders>

    <!--然后定义logger,只有定义了logger并引入的appender,appender才会生效-->
    <loggers>
        <!--过滤掉spring和mybatis的一些无用的DEBUG信息-->
        <logger name="org.springframework" level="warn"/>
        <logger name="org.mybatis" level="warn"/>
        <logger name="org.apache.kafka" level="warn"/>
        <root level="info">
            <appender-ref ref="Console"/>
            <appender-ref ref="RollingFileAll"/>
        </root>
    </loggers>
</configuration>

3、核心代码

java 复制代码
package com.youyou;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import com.documents4j.api.DocumentType;
import com.documents4j.api.IConversionJobWithPriorityUnspecified;
import com.documents4j.api.IConversionJobWithSourceSpecified;
import com.documents4j.api.IConversionJobWithSourceUnspecified;
import com.documents4j.api.IConversionJobWithTargetUnspecified;
import com.documents4j.api.IConverter;
import com.documents4j.job.LocalConverter;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

@Slf4j
public class Documents4jUtil {

    public static void main(String[] args) throws FileNotFoundException {
        File file = FileUtil.touch("D:\\Desktop\\SIU测试工装使用方法2.pdf");
        try (InputStream inputStream = IoUtil.toStream(FileUtil.file("D:\\Desktop\\SIU测试工装使用方法.docx"));
             OutputStream outputStream = new FileOutputStream(file)) {

            convertWordToPdf(inputStream, outputStream);

            System.out.println("完成");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * word转pdf
     */
    public static void convertWordToPdf(InputStream stream, OutputStream sourceOutput) {
        String os = System.getProperty("os.name").toLowerCase();
        log.info("convertWordToPdf 当前操作系统:{}", os);
        if (os.contains("win")) {
            // Windows操作系统
            windowsWordToPdf(stream, sourceOutput);
        } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
            // Unix/Linux/Mac操作系统
            linuxWordToPdf(stream, sourceOutput);
        } else {
            // 未知操作系统
            throw new RuntimeException("不支持当前操作系统转换文档。");
        }
    }

    /**
     * 通过documents4j 实现word转pdf -- Windows 环境 需要有 Microsoft Office 服务
     */
    public static void windowsWordToPdf(InputStream stream, OutputStream sourceOutput) {
        try {
            IConverter converter = LocalConverter.builder().build();
            IConversionJobWithSourceUnspecified convert = converter.convert(stream);
            IConversionJobWithSourceSpecified sourceSpecified = convert.as(DocumentType.DOCX);
            IConversionJobWithTargetUnspecified to = sourceSpecified.to(sourceOutput);
            IConversionJobWithPriorityUnspecified priorityUnspecified = to.as(DocumentType.PDF);
            boolean execute = priorityUnspecified.execute();
            log.info("转换结果:{}", execute);
            converter.shutDown();
        } catch (Exception e) {
            log.error("winWordToPdf windows环境word转换为pdf时出现异常:", e);
        }
    }

    /**
     * 通过libreoffice 实现word转pdf -- linux 环境 需要有 libreoffice 服务
     */
    public static void linuxWordToPdf(InputStream stream, OutputStream sourceOutput) {
        // 创建临时文件
        File tempFile = createTempFileFromInputStream(stream);
        // 构建LibreOffice的命令行工具命令
        String command = "libreoffice6.4 --headless --invisible --convert-to pdf " + tempFile.getAbsolutePath() + " --outdir " + tempFile.getParent();
        // 执行转换命令
        try {
            if (!executeLinuxCmd(command)) {
                throw new IOException("转换失败");
            }
            readPdfFileToByteArrayOutputStream(tempFile, sourceOutput);
        } catch (Exception e) {
            log.error("ConvertWordToPdf: Linux环境word转换为pdf时出现异常:" + e + tempFile.getPath());
            // 清理临时文件
            tempFile.delete();
        } finally {
            File pdfFile = new File(tempFile.getParent(), tempFile.getName().replace(".docx", ".pdf"));
            //清理转换后的pdf文件
            pdfFile.delete();
            // 清理临时文件,无论是否成功转换
            tempFile.delete();
        }
    }

    /**
     * 执行命令行
     *
     * @param cmd 命令行
     * @return
     * @throws IOException
     */
    private static boolean executeLinuxCmd(String cmd) throws IOException {
        Process process = Runtime.getRuntime().exec(cmd);
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            log.error("executeLinuxCmd 执行Linux命令异常:", e);
            Thread.currentThread().interrupt();
            return false;
        }
        return true;
    }

    /**
     * 创建临时文件
     */
    private static File createTempFileFromInputStream(InputStream inputStream) {
        try {
            File tempFile = File.createTempFile("temp_word", ".docx");
            Files.copy(inputStream, tempFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
            return tempFile;
        } catch (IOException e) {
            log.error("创建临时文件失败:", e);
            throw new RuntimeException("创建临时文件失败", e);
        }
    }

    /**
     * 读取pdf文件
     */
    private static void readPdfFileToByteArrayOutputStream(File tempFile, OutputStream sourceOutput) {
        try {
            Path outputFile = Paths.get(tempFile.getParent(), tempFile.getName().replace(".docx", ".pdf"));
            Files.copy(outputFile, sourceOutput);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

同时我也把相关代码上传到了gitee上地址如下:

word转PDF示例: documents4j组件将word文档转成pdf

相关推荐
AirDroid_cn4 小时前
PDF转图片需要用到什么技术?苹果手机怎样将PDF转为jpg?
pdf·iphone·ipad·快捷指令
拓端研究室12 小时前
专题:2025全球消费趋势与中国市场洞察报告|附300+份报告PDF、原数据表汇总下载
大数据·信息可视化·pdf
Kyln.Wu2 天前
【python实用小脚本-190】Python一键删除PDF任意页:输入页码秒出干净文件——再也不用在线裁剪排队
服务器·python·pdf
阿幸软件杂货间2 天前
免费万能电子书格式转换器!Neat Converter支持 ePub、Azw3、Mobi、Doc、PDF、TXT 文件的相互转换。
pdf·格式转换
星马梦缘3 天前
CSDN转PDF【无水印且免费!!!】
pdf·免费·pandoc·转pdf·无水印·csdn转pdf·wkhtmlpdf
画月的亮3 天前
前端处理导出PDF。Vue导出pdf
前端·vue.js·pdf
伊织code4 天前
pdfminer.six
python·pdf·图片·提取·文本·pdfminer·pdfminer.six
HAPPY酷4 天前
给纯小白的Python操作 PDF 笔记
开发语言·python·pdf
代码AI弗森5 天前
PDF OCR + 大模型:让文档理解不止停留在识字
pdf·ocr
小周同学:6 天前
在 Vue2 中使用 pdf.js + pdf-lib 实现 PDF 预览、手写签名、文字批注与高保真导出
开发语言·前端·javascript·vue.js·pdf