实现将docx转成PDF

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

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

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

1、导入依赖

<?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


logging:
  config: classpath:log4j2.xml

log4j2.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、核心代码

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

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用Java和LibreOffice(UNO API)可以将docx文件转换为pdf文件。下面是实现此操作的步骤: 1. 首先,需要安装LibreOffice软件并启动它。 2. 然后,使用Java代码连接到LibreOffice的UNO API。 3. 接下来,使用UNO API打开docx文件。 4. 然后,使用UNO API将docx文件转换为pdf文件。 5. 最后,关闭docx文件和LibreOffice。 下面是一个简单的Java代码示例,演示如何使用LibreOffice(UNO API)将docx文件转换为pdf文件: ```java import com.sun.star.beans.PropertyValue; import com.sun.star.frame.XComponentLoader; import com.sun.star.lang.XComponent; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.util.XCloseable; public class DocxToPdfConverter { public static void main(String[] args) { String inputFile = "input.docx"; String outputFile = "output.pdf"; XComponentContext context = null; XComponentLoader loader = null; XComponent document = null; try { // Connect to LibreOffice UNO API context = com.sun.star.comp.helper.Bootstrap.bootstrap(); loader = (XComponentLoader) UnoRuntime.queryInterface(XComponentLoader.class, context.getServiceManager().createInstanceWithContext("com.sun.star.frame.Desktop", context)); // Open docx file PropertyValue[] propertyValues = new PropertyValue[1]; propertyValues[0] = new PropertyValue(); propertyValues[0].Name = "Hidden"; propertyValues[0].Value = Boolean.TRUE; document = loader.loadComponentFromURL("file:///" + inputFile, "_blank", 0, propertyValues); // Convert docx to pdf PropertyValue[] convertProperties = new PropertyValue[2]; convertProperties[0] = new PropertyValue(); convertProperties[0].Name = "FilterName"; convertProperties[0].Value = "writer_pdf_Export"; convertProperties[1] = new PropertyValue(); convertProperties[1].Name = "Overwrite"; convertProperties[1].Value = Boolean.TRUE; ((com.sun.star.frame.XStorable) UnoRuntime.queryInterface(com.sun.star.frame.XStorable.class, document)).storeToURL("file:///" + outputFile, convertProperties); // Close docx file and LibreOffice ((XCloseable) UnoRuntime.queryInterface(XCloseable.class, document)).close(true); document.dispose(); context.getServiceManager().createInstanceWithContext("com.sun.star.bridge.UnoUrlResolver", context).queryInterface(XComponent.class).dispose(); context.dispose(); } catch (Exception e) { e.printStackTrace(); } } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值