最近公司有個需求,將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,然後將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;
}
速度還可以,沒有水印,不需要儲存到伺服器,基本都是流操作,完美!!!