需求: 将Office檔案作為文章并在網頁上預覽,主要為(Word、PPT、Excel)3種類型檔案。
研究了一下,找到了兩種解決方案
- 直接調用微軟的線上預覽功能實作(預覽前提:預覽資源必須可以直接通過公網通路到)微軟接口文檔
https://view.officeapps.live.com/op/view.aspx?src=http%3a%2f%2fvideo.ch9.ms%2fbuild%2f2011%2fslides%2fTOOL-532T_Sutter.pptx
在
src
後面拼接的就是要預覽的檔案位址(上面位址為官方預覽案例,可以直接在網頁中檢視)
- 将Office轉換為PDF在網頁中預覽
基于Office實作的解決方案
實作方式:在本地伺服器上安裝Microsoft Office,通過C#代碼調用伺服器上的COM接口,将Office檔案轉換為PDF(類似于用Office軟體打開Word文檔,然後另存為PDF檔案)。
通過Nuget包管理器安裝需要的包(這些包隻能在
.Net FrameWork
版本項目中使用)
Microsoft.Office.Interop.Word
Microsoft.Office.Interop.PowerPoint
Microsoft.Office.Interop.Excel
代碼:
public class OfficeHelper
{
static Word.Application wordApplication = new Word.Application();
static Excel.Application excelApplication = new Excel.Application();
static PowerPoint.Application pptApplication = new PowerPoint.Application();
/// <summary>
/// 将Word文檔轉換成PDF格式
/// </summary>
/// <param name="sourcePath">源檔案路徑</param>
/// <param name="targetPath">目标檔案路徑</param>
/// <returns></returns>
public static bool WordConvertPDF(string sourcePath, string targetPath)
{
bool result;
Word.Document wordDocument = null;
try
{
wordDocument = wordApplication.Documents.Open(ref sourcePath);
if (wordDocument != null)
{
wordDocument.SaveAs2(targetPath, WdExportFormat.wdExportFormatPDF);
//wordDocument.ExportAsFixedFormat(targetPath, WdExportFormat.wdExportFormatPDF);
result = true;
}
}
catch (Exception ex)
{
result = false;
LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
}
finally
{
if (wordDocument != null)
{
wordDocument.Close();
wordDocument = null;
}
}
return result;
}
/// <summary>
/// 将Excel文檔轉換成PDF格式
/// </summary>
/// <param name="sourcePath">源檔案路徑</param>
/// <param name="targetPath">目标檔案路徑</param>
/// <returns></returns>
public static bool ExcelConvertPDF(string sourcePath, string targetPath)
{
bool result;
Workbook workBook = null;
try
{
workBook = excelApplication.Workbooks.Open(sourcePath);
if (workBook != null)
{
workBook.ExportAsFixedFormat(XlFixedFormatType.xlTypePDF, targetPath);
result = true;
}
}
catch (Exception ex)
{
result = false;
LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
}
finally
{
if (workBook != null)
{
workBook.Close();
workBook = null;
}
}
return result;
}
/// <summary>
/// 将PPT文檔轉換成pdf格式
/// </summary>
/// <param name="sourcePath">源檔案路徑</param>
/// <param name="targetPath">目标檔案路徑</param>
/// <returns></returns>
public static bool PPTConvertPDF(string sourcePath, string targetPath)
{
bool result;
object missing = Type.Missing;
Presentation persentation = null;
try
{
persentation = pptApplication.Presentations.Open(sourcePath, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse);
if (persentation != null)
{
persentation.SaveAs(targetPath, PpSaveAsFileType.ppSaveAsPDF, Microsoft.Office.Core.MsoTriState.msoTrue);
//persentation.ExportAsFixedFormat(targetPath, PpFixedFormatType.ppFixedFormatTypePDF);
result = true;
}
}
catch (Exception ex)
{
result = false;
LogHelper.Log($"檔案:{sourcePath} 生成失敗,原因:{ex.Message}", ex.StackTrace);
}
finally
{
if (persentation != null)
{
persentation.Close();
persentation = null;
}
}
return result;
}
}
Office COM API提供
SaveAs
和
ExportAsFixedFormat
兩個方法來生成文檔,需要注意調用時參數不同,大部分使用預設值就可以了(接口文檔位址)。
上面代碼中将
wordApplication
作為一個靜态變量提出來,每次在加載檔案時,再通過它打開(相當于一直開着Office.Word程式)。在我本地測試時,本地安裝的是Microsoft Office 2016版本,代碼運作一直正常。當我把程式給發給别人使用時,發現隻有在第一次處理Word檔案時轉換成功,之後的檔案轉換都失敗了。
經檢查,由于對方電腦上安裝的是Office365版本,有可能是在第一次處理完檔案後
wordApplication
對象就關閉了,進而導緻後面的檔案都無法正常轉換。修改代碼,每次轉換前都去重新執行個體化
Word.Application
(相當于重新打開一遍Office.Word程式),雖然每次執行個體化導緻效率很低,但是所有檔案都處理成功了。最神奇的是同一環境下
pptApplication
的連續調用是正常的,目前還不知道問題的具體原因,有了解的小夥伴可以告訴我一下。
直接調Office的COM元件有版本相容的問題,可以采用NetOffice間接調用。
通過Nuget安裝NetOffice,不同的Office檔案需要引用不同的Apidll
using NetOffice;
using NetOffice.PowerPointApi;
public static void PPTConvertPDF(string sourcePath, string targetPath)
{
using (Application _pptApp = new Application())
{
var pres = _pptApp.Presentations.Open(sourcePath, NetOffice.OfficeApi.Enums.MsoTriState.msoCTrue, NetOffice.OfficeApi.Enums.MsoTriState.msoFalse, NetOffice.OfficeApi.Enums.MsoTriState.msoFalse);
pres.SaveAs(targetPath, NetOffice.PowerPointApi.Enums.PpSaveAsFileType.ppSaveAsPDF);
pres.Close();
}
}
方法參數需要F12進去看參數提醒描述
基于第三方插件實作的解決方案
這裡主要介紹下Spire和GemBox兩個插件,他們都可以在伺服器上沒有安裝Office軟體的情況下直接處理檔案。
PS: 正式版收費使用,不然生成的文檔中會帶有水印。免費版會有一些限制,比如建立或讀取
Office
檔案時有頁數限制,若超出限制直接抛異常。
這裡簡單介紹下代碼,詳細的api可以到插件官網文檔中去探索。
- Free Spire.Doc for .NET
public static void WordConvertPDF(string sourcePath, string targetPath)
{
using (var doc = new Document(sourcePath))
{
doc.SaveToFile(targetPath, Spire.Doc.FileFormat.PDF);
}
}
- GemBox.Document free version
public static void WordConvertPDF(string sourcePath, string targetPath)
{
// If using Professional version, put your serial key below.
ComponentInfo.SetLicense("FREE-LIMITED-KEY");
DocumentModel document = DocumentModel.Load(sourcePath);
document.Save(targetPath, SaveOptions.PdfDefault);
}
基于WPS實作的解決方案
這個和基于Office的解決方案一樣,通過代碼調用COM接口,實作檔案的轉換。當然需要提前在伺服器上安裝WPS軟體。
在本地的WPS安裝目錄中,找到以下幾個dll檔案,并将其引用到項目中,
wpsapi.dll
wpsapiex.dll
public static void WordConvertPDF(string sourcePath, string targetPath)
{
var app = new Word.Application();
var doc = app.Documents.Open(sourcePath,Visible: MsoTriState.msoFalse);
doc.SaveAs2(targetPath, Word.WdExportFormat.wdExportFormatPDF);
doc.Close();
app.Close();
}
其中
Word
是
wpsapi.dll
添加到程式中後,程式集命名空間名稱。
調用WPS轉換文檔我也隻是在本機運作成功了,并沒有實際的應用,隻能說是多做了一下了解和嘗試吧。
總結
将Office檔案轉為PDF檔案已經成功了,在網頁中預覽PDF檔案就簡單了,甚至有的浏覽器直接預設可以打開預覽PDF檔案。這個網上的解決方案已經很多了,最後選擇了通過
pdf.js
在頁面上預覽。預覽檔案已經有了,剩下的就差一個封面了,幹巴巴的标題太枯燥,圖文并茂才是王道,标題黨也需要一些“切合實際”的圖檔來烘托一下氣氛吧!
是以自然而然就有了這個問題,如何給文檔設定一個合适的封面圖呢?馬上想到一個辦法自己挑一張順眼的圖檔作為封面(好吧這是廢話)。認真思考一下有下面幾種解決方案:
- 擷取Office檔案内部的圖檔作為封面
- 擷取PDF預覽檔案的第一頁作為封面
預知後事如何,且聽下回分解(畢竟我也還沒有寫完啊!~~~~)。