最近公司有個需求,將PPT課件轉成圖片列表,然后在前端展示成輪播圖,於是一開始通過Microsoft.Office.Interop.PowerPoint包實現了這個需求具體代碼如下:
/// <summary> /// 將PPT轉換為圖片 /// </summary> /// <param name="pptPath"></param> /// <param name="imgPath"></param> public static List<string> UploadPptImage(HttpRequestBase request) { var imgUrls = new List<string>(); var file = request.Files["ppt_file"]; if (string.IsNullOrEmpty(file.FileName)) { return new List<string>(); } var path = AppDomain.CurrentDomain.BaseDirectory + "imagesfromppt/" + file.FileName; var savepath = AppDomain.CurrentDomain.BaseDirectory + "ppt/"; if (!System.IO.Directory.Exists(path)) { System.IO.Directory.CreateDirectory(path); } if (!System.IO.Directory.Exists(savepath)) { System.IO.Directory.CreateDirectory(savepath); } var filepath = Path.Combine(savepath, file.FileName); file.SaveAs(filepath); Microsoft.Office.Interop.PowerPoint.Application application = null; Presentation persentation = null; var imagPathList = new List<string>(); try { application = new Microsoft.Office.Interop.PowerPoint.Application(); persentation = application.Presentations.Open(filepath); //persentation.Slides[1].Export(path + "\\page" + 1 + ".jpg", "JPG", 800, 600); for (var k = 1; k <= persentation.Slides.Count; k++) { var imgPath = path + "\\page" + k + ".jpg"; imagPathList.Add(imgPath); persentation.Slides[k].Export(imgPath, "JPG", 800, 600); } imagPathList.ForEach(p => { using (MemoryStream ms = new MemoryStream()) { using (var fs = new FileStream(p, FileMode.Open)) { byte[] buffer = new byte[1024]; int result = 0; while ((result = fs.Read(buffer, 0, buffer.Length)) > 0) { ms.Write(buffer, 0, result); } } ms.Seek(0, SeekOrigin.Begin); var fileData = ms.ToArray(); string url = ;//此處為雲存儲,不重要,上傳后獲得url imgUrls.Add(url); } }); } catch (Exception ex) { //記錄異常 } finally { if (persentation != null) { persentation.Close(); persentation = null; } if (application != null) { application.Quit(); application = null; } GC.Collect(); GC.WaitForPendingFinalizers(); imagPathList.ForEach(p => { if (File.Exists(p)) { File.Delete(p); } }); if (File.Exists(filepath)) { File.Delete(filepath); } if (Directory.Exists(path)) { Directory.Delete(path); } } return imgUrls; }
由於我們圖片都是雲存儲,所以存到文件系統后又刪掉了,貌似沒有直接存成流的方式,不重要
發布到線上后發現服務器沒有安裝office,因此無法正常使用,但又不能在服務器上安裝,因此踩坑一天左右,找到了一些方法
一、使用Spire.Presentation
使用Spire.Presentation可以輕松的將ppt轉換為image,代碼如下
/// <summary> /// 將PPT轉換為圖片 /// </summary> /// <param name="pptPath"></param> /// <param name="imgPath"></param> public static List<string> UploadPptImage(HttpRequestBase request) { var imgUrls = new List<string>(); var file = request.Files["ppt_file"]; if (string.IsNullOrEmpty(file.FileName)) { return new List<string>(); } Presentation ppt = new Presentation(); ppt.LoadFromStream(file.InputStream, FileFormat.Auto); var slidescount = ppt.Slides.Count; try { if (slidescount > 0) { for (int i = 0; i < slidescount; i++) { ppt.Slides[i].SaveAsImage();//把ppt轉換成emf格式圖片 Image image = ppt.Slides[i].SaveAsImage(); using (var ms = new MemoryStream()) { image.Save(ms, ImageFormat.Png); ms.Seek(0, SeekOrigin.Begin); var fileData = ms.ToArray(); string url = ;//雲存儲,返回url imgUrls.Add(url); } } } } catch (Exception ex) { //記錄異常 } return imgUrls; }
可以看到,代碼簡單,並且不需要存儲到服務器上,但是Spire.Presentation是商用的,免費使用有10頁的限制,並且會有水印
於是繼續尋找方法
二、最后解決方案是,先將PPT轉換為pdf(這里使用Aspose.Slides),然后將pdf文件轉換為圖片,這里也貼出一些常見的文章鏈接:
文章中使用的方法我沒有全試,總結一下優缺點:
1、O2S.Components.PDFRender4NET.dll
該dll可用,雖然免費版有水印但是網上還是能找到破解的,這里不貼了,但ppt中使用了png格式的圖片,會丟失,並且使用圖片清晰度調大會很卡
2、Acrobat.dll
該dll在asp .net環境下,直接無法添加引用,不知道是不是我自己的問題
3. PDFLibNet.dll
該dll只支持32位的,我嘗試過,沒有成功,報錯了,可能是我自己的問題
4. Ghostscript
網上很多人都采用這個方法(貌似功能很強大),博主覺得代碼復雜,沒有深入研究。不適用
上面是我試過的方法,可能是我自己的原因,最后不盡如人意,於是我繼續找,看到了一篇文章:
文章使用
PdfiumViewer包來實現,參照代碼寫了一下,原代碼是winform的。
最后引用了nuget包PdfiumViewer,但是報錯:找不到一個叫PDFium的dll文件,於是我找到了github,發現有人改源代碼實現了,但是我比較菜,自己改不動,於是放棄
后面又嘗試了一遍,發現nuget中這個包的作者有上傳了另外兩個包,看起來是用來處理這個問題的,於是我嘗試引用了其中一個,還不行,引用另一個,可以了:
包名是PdfiumViewer.Native.x86.v8-xfa和PdfiumViewer.Native.x86_64.v8-xfa
最后貼出代碼:
/// <summary> /// 將PPT轉換為圖片 /// </summary> /// <param name="pptPath"></param> /// <param name="imgPath"></param> public static List<string> UploadPptImage(HttpRequestBase request) { var imgUrls = new List<string>(); var file = request.Files["ppt_file"]; if (string.IsNullOrEmpty(file.FileName)) { return new List<string>(); } Presentation ppt = new Presentation(file.InputStream); using (var mspdf = new MemoryStream()) { var pageCount = ppt.Slides.Count; ppt.Save(mspdf, Aspose.Slides.Export.SaveFormat.Pdf); using (var pdf = PdfDocument.Load(mspdf)) { try { var pagesizes = pdf.PageSizes; for (int i = 0; i < pdf.PageCount; i++) { Size size = new Size(); size.Height = (int)pagesizes[(i)].Height; size.Width = (int)pagesizes[(i)].Width; using (var image = pdf.Render(i, size.Width, size.Height, PdfRenderFlags.Annotations)) { using (var ms = new MemoryStream()) { image.Save(ms, ImageFormat.Png); ms.Seek(0, SeekOrigin.Begin); var fileData = ms.ToArray(); string url = ;//雲存儲,返回url imgUrls.Add(url); } } } } catch (Exception ex) { //異常記錄 } } } return imgUrls; }
速度還可以,沒有水印,不需要存儲到服務器,基本都是流操作,完美!!!