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