使用LibreOffice将office文档转pdf(java实现)

由于项目需要实现office文档在浏览器里预览,找了几种方案测试了一下,先采用的openoffice进行了测试,这个方案是在linux服务器上安装openOffice然后通过openOffice命令来转换pdf。在测试转换文档过程中频繁出现openoffice服务崩溃的现象,然后就弃用了。后来又看到java通过jacob来调用com组件实现转换的方案,但是只能在windows环境下使用,而我们线上环境都是linux环境,所以果断放弃,当然也有不少收费的商业产品方案。

最后在同事的推荐下,使用openoffice的升级版libreoffice进行了实现,效果还不错。

LibreOffice安装

我的服务端的环境是centos7和libreoffice5.3,安装步骤参考这遍文章

https://blog.csdn.net/weixin_50236329/article/details/119860056

下载字体
yum groupinstall "fonts"

修改字符集
vim /etc/locale.conf
将LANG="en_US.UTF-8"修改成LANG="zh_CN.UTF-8"

最后重启
reboot

安装完成后,输入命令soffice --version,会显示如下版本信息,如果提示没有soffice命令,需要增加环境变量,或者是安装的有问题。

java调用

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;

/**
 * office文件转pdf工具类
 */
public class Office2PDFUtils {
    private static final Logger log = LoggerFactory.getLogger(Office2PDFUtils.class);


    /**
     * 将office文档转成pdf文件
     * @param sourcePath
     * @param targetPath
     * @throws Exception
     */
    public static boolean word2pdf(String sourcePath, String targetPath) throws Exception {
        if (!new File(sourcePath).exists()) {
            throw new FileNotFoundException();
        }
        String command = String.format("soffice --convert-to pdf:writer_pdf_Export %s --outdir %s", sourcePath, targetPath);
        boolean flag = executeCommand(command);
        log.info("word2pdf: convert pdf complete. flag="+flag);
        return flag;
    }

    /**
     * 执行libreoffice的转换命令
     * @param command
     * @return
     */
    public static boolean executeCommand(String command){
        try {
            long start = System.currentTimeMillis();
            Process process = Runtime.getRuntime().exec(command);
            // 返回值是子线程执行完毕的返回值,返回0表示正常结束
            int exitStatus = process.waitFor();
            log.info("executeCommand: convert pdf exitStatus= " + exitStatus);

            // 销毁子进程
            process.destroy();
            long end = System.currentTimeMillis();
            log.info("executeCommand: convert pdf cost time " + (end - start) + "ms");
            return exitStatus == 0;
        }catch (Exception e){
            log.error("executeCommand: runtime exec error", e);
        }
        return false;
    }

}
public static void main(String[] args) throws Exception {
    String source = "/Users/lucy/test/word-testV1.0.docx";
    String target = "/Users/lucy/test/";
    InputStream inputStream = Office2PDFUtils.word2pdf(source, target);
}

 总结

针对普通office文件的转换都还OK,但是有几个坑,第一个是需要转换的office文档如果文件名中包含的有空格会转换失败,需要转换的时候将空格处理掉;第二个是文档里如果有比较复杂的表格和visio元素会转换失败;后来又安装libreoffice7.2的版本测试了一下,能转换成功解决掉这些坑,但是转换的速度很慢,如果场景仅仅是后台去进行转换,对转换的时间没有要求,可以进行异步线程去处理转换,同步调用的话很可能会超时。如果公司或者项目有条件的话,可以去购买商业产品进行集成,省事节省时间,没有什么坑,有丰富的实践案例,

参考文章:【libreoffice】libreoffice实现office转pdf、html、jpg等格式数据_weixin_34032779的博客-CSDN博客

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
可以使用Java中的Uno API来实现LibreOfficeOffice文档换为PDF的功能。具体实现步骤如下: 1. 首先需要安装LibreOffice,并启动LibreOffice服务。启动命令为: ``` soffice --headless --accept="socket,host=127.0.0.1,port=8100;urp;" ``` 2. 在Java使用Uno API连接LibreOffice服务,代码示例如下: ``` XComponentContext xContext = Bootstrap.bootstrap(); XMultiComponentFactory xMCF = xContext.getServiceManager(); Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); XComponentLoader xCompLoader = UnoRuntime.queryInterface(XComponentLoader.class, oDesktop); ``` 3. 加载需要换的Office文档,代码示例如下: ``` String inputUrl = "file:///path/to/input.docx"; PropertyValue[] loadProps = new PropertyValue[1]; loadProps[0] = new PropertyValue(); loadProps[0].Name = "Hidden"; loadProps[0].Value = Boolean.TRUE; XComponent xDoc = xCompLoader.loadComponentFromURL(inputUrl, "_blank", 0, loadProps); ``` 4. 将文档换为PDF格式,代码示例如下: ``` String outputUrl = "file:///path/to/output.pdf"; PropertyValue[] convertProps = new PropertyValue[2]; convertProps[0] = new PropertyValue(); convertProps[0].Name = "FilterName"; convertProps[0].Value = "writer_pdf_Export"; convertProps[1] = new PropertyValue(); convertProps[1].Name = "Overwrite"; convertProps[1].Value = Boolean.TRUE; XStorable xStore = UnoRuntime.queryInterface(XStorable.class, xDoc); xStore.storeToURL(outputUrl, convertProps); ``` 5. 最后需要关闭文档LibreOffice服务,代码示例如下: ``` xDoc.dispose(); System.exit(0); ``` 完整的代码示例如下: ``` import com.sun.star.comp.helper.Bootstrap; import com.sun.star.frame.XComponentLoader; import com.sun.star.frame.XStorable; import com.sun.star.lang.XComponent; import com.sun.star.lang.XMultiComponentFactory; import com.sun.star.uno.UnoRuntime; import com.sun.star.uno.XComponentContext; import com.sun.star.beans.PropertyValue; public class OfficeToPdfConverter { public static void main(String[] args) { try { // Connect to LibreOffice service XComponentContext xContext = Bootstrap.bootstrap(); XMultiComponentFactory xMCF = xContext.getServiceManager(); Object oDesktop = xMCF.createInstanceWithContext("com.sun.star.frame.Desktop", xContext); XComponentLoader xCompLoader = UnoRuntime.queryInterface(XComponentLoader.class, oDesktop); // Load input document String inputUrl = "file:///path/to/input.docx"; PropertyValue[] loadProps = new PropertyValue[1]; loadProps[0] = new PropertyValue(); loadProps[0].Name = "Hidden"; loadProps[0].Value = Boolean.TRUE; XComponent xDoc = xCompLoader.loadComponentFromURL(inputUrl, "_blank", 0, loadProps); // Convert document to PDF String outputUrl = "file:///path/to/output.pdf"; PropertyValue[] convertProps = new PropertyValue[2]; convertProps[0] = new PropertyValue(); convertProps[0].Name = "FilterName"; convertProps[0].Value = "writer_pdf_Export"; convertProps[1] = new PropertyValue(); convertProps[1].Name = "Overwrite"; convertProps[1].Value = Boolean.TRUE; XStorable xStore = UnoRuntime.queryInterface(XStorable.class, xDoc); xStore.storeToURL(outputUrl, convertProps); // Close document and exit xDoc.dispose(); System.exit(0); } catch (Exception e) { e.printStackTrace(); } } } ``` 需要注意的是,在使用Uno API连接LibreOffice服务时,需要在classpath中加入相应的jar包。具体jar包名称和路径可以参考LibreOffice的安装目录。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值