C# Asp.Net 实现PPT/PDF转成图片(不依赖office)
最近公司有个需求,将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文件转换为图片,这里也贴出一些常见的文章链接:
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;
}
速度还可以,没有水印,不需要存储到服务器,基本都是流操作,完美!!!