Java 利用LibreOffice將Office文檔轉換成 PDF,進而轉圖片,實現在線預覽功能


異步轉換

通過調用操作系統命令的方式實現,這個轉換是異步的,根據文件的大小需要的時間不確定,如果在上傳之后就要立即預覽,需要用同步方式。 - 優點:實現方式簡單,不需要額外配置信息,不需要添加第三方依賴庫(當然 LibreOffice 是必須要安裝的)。 - 缺點:發送指令之后,轉換是否成功,是否有異常,無法獲知,也就是說,轉換是否成功,是不確定的。當然,通過嚴格的測試,一般還是可以保證轉換的可靠性的。

同步轉換

用到了 JodConverter: - 優點:轉換是同步的,轉換成功與否是確定的。 - 缺點:代碼運行期需要啟動 LibreOffice 服務,需要占用操作系統資源,相對於異步轉換方式,需要依賴第三方庫,需要額外配置信息。

添加依賴(僅同步方式需要)

<dependency>
    <groupId>org.jodconverter</groupId>
    <artifactId>jodconverter-local</artifactId>
    <version>4.2.4</version>
</dependency>

在 resources 目錄yml 文件配置參數(僅同步方式需要)

libreOffice:
  ##LibreOffice安裝主目錄
  libreOfficeHome: C:/Program Files/LibreOffice
  ##開啟多個LibreOffice進程,每個端口對應一個進程
  portNumbers: 2002
  ##任務執行超時為5分鍾
  taskExecutionTimeoutMinutes: 5
  ##任務隊列超時為1小時
  taskQueueTimeoutHours: 1

轉換類 LibreOfficeUtil

import org.jodconverter.JodConverter;
import java.io.File;

public class LibreOfficeUtil {

    /*
     * 同步轉換
     * @Date    2021年11月09日 11:41:04
     * @Param   [sourceFile, targetFile]
     * @Return  boolean
     */
    public static boolean convertOffice2PDFSyncIsSuccess(File sourceFile, File targetFile) {
        try {
            OfficeManagerInstance.start();
            JodConverter.convert(sourceFile).to(targetFile).execute();
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 利用 LibreOffice 將 Office 文檔轉換成 PDF,該轉換是異步的,返回時,轉換可能還在進行中,轉換是否有異常也未可知
     * @param filePath       目標文件地址
     * @param targetFilePath 輸出文件夾
     * @return 子線程執行完畢的返回值
     */
    public static int convertOffice2PDFAsync(String filePath, String fileName, String targetFilePath) throws Exception {
        String command;
        int exitStatus;
        String osName = System.getProperty("os.name");
        String outDir = targetFilePath.length() > 0 ? " --outdir " + targetFilePath : "";

        if (osName.contains("Windows")) {
            command = "cmd /c cd /d " + filePath + " && start soffice --headless --invisible --convert-to pdf ./" + fileName + outDir;
        } else {
            command = "libreoffice --headless --invisible --convert-to pdf:writer_pdf_Export " + filePath + fileName + outDir;
        }

        exitStatus = executeOSCommand(command);
        return exitStatus;
    }

    /**
     * 調用操作系統的控制台,執行 command 指令
     * 執行該方法時,並沒有等到指令執行完畢才返回,而是執行之后立即返回,返回結果為 0,只能說明正確的調用了操作系統的控制台指令,但執行結果如何,是否有異常,在這里是不能體現的,所以,更好的姿勢是用同步轉換功能。
     */
    private static int executeOSCommand(String command) throws Exception {
        Process process;
        process = Runtime.getRuntime().exec(command); // 轉換需要時間,比如一個 3M 左右的文檔大概需要 8 秒左右,但實際測試時,並不會等轉換結束才執行下一行代碼,而是把執行指令發送出去后就立即執行下一行代碼了。

        int exitStatus = process.waitFor();

        if (exitStatus == 0) {
            exitStatus = process.exitValue();
        }

        // 銷毀子進程
        process.destroy();
        return exitStatus;
    }
}

OfficeManagerInstance(僅同步方式需要)

import org.jodconverter.office.LocalOfficeManager;
import org.jodconverter.office.OfficeManager;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;

@Component
public class OfficeManagerInstance {
    private static OfficeManager INSTANCE = null;

    @Value("${libreOffice.libreOfficeHome}")
    private String prilibreOfficeHome;
    @Value("${libreOffice.portNumbers}")
    private String portNumbers;
    @Value("${libreOffice.taskExecutionTimeoutMinutes}")
    private String taskExecutionTimeoutMinutes;
    @Value("${libreOffice.taskQueueTimeoutHours}")
    private String taskQueueTimeoutHours;

    public static synchronized void start() {
        officeManagerStart();
    }

    @PostConstruct
    private void init() {
        try {
            String[] portNum = portNumbers.split(",");
            int[] ports = new int[portNum.length];
            for (int i = 0; i < portNum.length; i++) {
                ports[i] = Integer.parseInt(portNum[i]);
            }
            LocalOfficeManager.Builder builder = LocalOfficeManager.builder().install();
            builder.officeHome(prilibreOfficeHome);
            builder.portNumbers(ports);
            builder.taskExecutionTimeout(Integer.parseInt(taskExecutionTimeoutMinutes) * 1000 * 60); // minute
            builder.taskQueueTimeout(Integer.parseInt(taskQueueTimeoutHours) * 1000 * 60 * 60); // hour
            INSTANCE = builder.build();
            officeManagerStart();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void officeManagerStart() {
        if (INSTANCE.isRunning()) {
            return;
        }

        try {
            INSTANCE.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

CentOS 7.5 / 7.6 / 7.7安裝libreoffice 5.3.6.1過程方法arm

---目前CentOS 7.5、7.6和7.7的arm版本都自帶libreoffice 5.3.6.1版本

【安裝過程】

1、掛載系統ISO鏡像並配置本地yum源(無法訪問互聯網時需要執行此步驟,可以訪問互聯網直接跳過)

掛載OS鏡像:mount -o loop /home/CentOS-7-aarch64-Everything-1810.iso   /mnt/CentOS/

修改/etc/yum.repos.d/CentOS-Base.repo文件,配置yum本地源:

[base]

name=CentOS-$releasever   - Base

#mirrorlist=http://mirrorlist.centos.org/?release=$releasever&arch=$basearch&repo=os&infra=$infra

baseurl=   file:///mnt/CentOS

gpgcheck=1

gpgkey=   file:///mnt/CentOS/RPM-GPG-KEY-CentOS-7

file:///mnt/CentOS/RPM-GPG-KEY-CentOS-7-aarch64

運行下面的命令,使yum源配置生效:

yum clean all

yum makecache

yum安裝GCC等相關依賴:

sudo yum install -y snappy snappy-devel autoconf automake libtool   git gcc gcc-c++ make cmake openssl openssl-devel ncurses-devel zlib   zlib-devel bzip2 bzip2-devel bzip2-libs readline readline-devel bison zip   unzip tar tcl java-1.8.0* bison* ncurses*

2、執行yum命令直接安裝

yum -y install libreoffice*

3、查看libreoffice版本及幫助信息

libreoffice --version

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM