現實場景中要實現Word格式轉PDF格式還是比較常見的。
如果要用開源的組件,只有用Libreoffice了。
一、下載安裝Libreoffice
先進入如下鏈接,找到最新版本和匹配的操作系統來安裝。
官網試過,下載是能下載,但安裝了用不了,下面的鏈接是鏡像。
https://mirrors.cloud.tencent.com/libreoffice/libreoffice/stable/
二、下面是C#的幫助類中的方法:
/// <summary>
/// 從網絡上的Word文件,獲取到pdf, 保存到臨時文件。后續需要寫代碼刪除這個臨時文件,否則會占用服務器資源
/// </summary>
/// <param name="docUrl"></param>
/// <returns></returns>
public static string WordUrl2Pdf(string docUrl)
{try{int rand = new Random().Next(1000, 9999);var tempWord = $"d:\\tmp\\Convert\\{rand}.docx";var tempPdf = $"d:\\tmp\\Convert\\{rand}.pdf";FileHelper.DownloadAndSave(docUrl, tempWord);Word2Pdf(tempWord, tempPdf);File.Delete(tempWord);return tempPdf;}catch (Exception ex){Console.WriteLine(ex.Message);return null;}
}/// <summary>
/// 將 Word 文件轉換為 PDF
/// </summary>
/// <param name="docPath">Word 文件路徑</param>
/// <param name="pdfPath">輸出 PDF 文件路徑</param>
public static void Word2Pdf(string docPath, string pdfPath)
{// 檢查輸入文件是否存在if (!File.Exists(docPath)){throw new FileNotFoundException("輸入文件不存在!", docPath);}// 確保輸出目錄存在string outputDir = System.IO.Path.GetDirectoryName(pdfPath);if (!Directory.Exists(outputDir)){Directory.CreateDirectory(outputDir);}// 定義 LibreOffice 路徑和動態端口號string libreOfficePath = @"d:\Program Files\LibreOffice\program\soffice.exe";int port = GetUniquePort(); // 獲取唯一端口號// 啟動 LibreOffice 實例并執行轉換Process process = new Process();process.StartInfo.FileName = libreOfficePath;process.StartInfo.Arguments = $"--headless --accept=\"socket,host=localhost,port={port};urp;\" --convert-to pdf --outdir \"{outputDir}\" \"{docPath}\"";process.StartInfo.UseShellExecute = false;process.StartInfo.CreateNoWindow = true;try{Console.WriteLine($"正在轉換文件 {docPath} -> {pdfPath},使用端口: {port}");process.Start();process.WaitForExit();if (process.ExitCode != 0){throw new Exception($"轉換失敗,退出代碼: {process.ExitCode}");}}catch (Exception ex){throw new Exception($"轉換文件 {docPath} 時發生錯誤: {ex.Message}", ex);}finally{// 確保進程結束if (!process.HasExited){process.Kill();}}
}/// <summary>
/// 獲取唯一的端口號
/// </summary>
/// <returns>唯一端口號</returns>
private static int GetUniquePort()
{// 使用 Interlocked.Increment 確保線程安全int basePort = 2002; // 起始端口號return basePort + Interlocked.Increment(ref _portCounter);
}private static int _portCounter = 0; // 全局計數器,用于生成唯一端口號