1. 程式人生 > 其它 >Java 利用LibreOffice將Office文件轉換成 PDF,進而轉圖片,實現線上預覽功能

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.prilibreOfficeHome}")
    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