MVC 附件在线预览
原因:应客户需求,在系统中浏览附件内容,需要先下载到本地然后打开,对使用造成了不便,要求可以不需下载直接在浏览器中打开减少操作步骤。
领导给了3天时间,最后查找方法,写测试项目,往正式项目添加,测试,修bug,优化下来总共花费了大概两天多时间。下面给出解决经验,主要把遇到的坑
给说一下。
1.研究方案
参考:http://www.cnblogs.com/xuse/p/3710647.html
使用FlexPaper实现office文件的预览(C#版)
http://www.cnblogs.com/zzPrince/p/3378336.html
flexpaper使用:
http://www.cnblogs.com/Gnepner/archive/2011/08/19/2145493.html
通过研究发现,网上流传很多方法可以实现该需求,排除第三方控件的话,有两种比较流行,一种是把文档转化为swf格式,还有一种是转化为html实现在线预览。
但是按照网上的原话,转化为html方法很不科学,转换的文件格式丢失,仅限于IIS服务器,利用asp.net。配置麻烦,正如微软所说,读取office不是这么干的,鉴于此
先尝试另一种方案。
原理:先将office转换为PDF,再转换为SWF,最后通过网页加载Flash预览。
2.搭建测试项目
2.1工具:
a.安装Microsoft Office 2007以上版本,主要是需要用到里面四个类库,稍后列出。
b.Swftools
下载地址:http://www.swftools.org/download.html
这有个小坑,看好要下载window版。
c.flexpaper
下载地址:http://flexpaper.devaldi.com/download.htm
2.2搭建测试项目
由于本系统用的是Mvc开发,所以先建了一个MvcTest项目。
添加引用,此处有小坑,注意在引用的类库上右键,把嵌入互操作类型改为False,
引用版本最好12.0.0.0,14.0.0.0经测试也可用,网上说存在权限认证问题。
添加工具,项目文件
a.Common>Utils里面写Word,Excel,PPT等转化为PDF的方法,网上有很多,主要是Excel的转化经测试有一些有问题,贴一个靠谱的
1 public static bool ExcelToPDF(string sourcePath, string targetPath) 2 { 3 bool result = false; 4 Excel.XlFixedFormatType targetType = Excel.XlFixedFormatType.xlTypePDF; 5 object missing = Type.Missing; 6 Excel.ApplicationClass application = null; 7 Excel.Workbook workBook = null; 8 try 9 { 10 application = new Excel.ApplicationClass(); 11 object target = targetPath; 12 object type = targetType; 13 workBook = application.Workbooks.Open(sourcePath, missing, missing, missing, missing, missing, 14 missing, missing, missing, missing, missing, missing, missing, missing, missing); 15 16 workBook.ExportAsFixedFormat(targetType, target, Excel.XlFixedFormatQuality.xlQualityStandard, true, false, missing, missing, missing, missing); 17 result = true; 18 } 19 catch 20 { 21 result = false; 22 } 23 finally 24 { 25 if (workBook != null) 26 { 27 workBook.Close(true, missing, missing); 28 workBook = null; 29 } 30 if (application != null) 31 { 32 application.Quit(); 33 application = null; 34 } 35 GC.Collect(); 36 GC.WaitForPendingFinalizers(); 37 GC.Collect(); 38 GC.WaitForPendingFinalizers(); 39 } 40 return result; 41 42 }
b.修改控制器
先在HomeController控制器的视图里里添加一个链接
<div> <input id="fileName" name="fileName" type="text" style="width:100px;"/> <a href="#" onclick="preview();" >预览</a> </div> <script type="text/javascript"> function preview() { var name=$("#fileName").val(); window.open("/Home/Preview?name=" + name); } </script>
再在控制器里添加一个方法:
public ActionResult Preview(string name="") { string url = "/FlexPaper/Index?filePath=~/UploadFiles/" + name; return Redirect(url); }
测试用RedirectToAction的方法走不到FlexPaper控制器里,貌似是路由的问题,为节省时间直接使用Redirect方法,成功进去了。
然后新建一个FlexPaperController控制器,里面写的有自己从网上down的代码,加上自己的优化,判断文件是否存在,删除旧文件,是否可转化等等提示。
1 public class FlexPaperController : Controller 2 { 3 4 string pdf2swfToolPath = System.Web.HttpContext.Current.Server.MapPath("~/FlexPaper/pdf2swf.exe"); 5 string png2swfToolPath = System.Web.HttpContext.Current.Server.MapPath("~/FlexPaper/png2swf.exe"); 6 string jpeg2swfToolPath = System.Web.HttpContext.Current.Server.MapPath("~/FlexPaper/jpeg2swf.exe"); 7 string gif2swfToolPath = System.Web.HttpContext.Current.Server.MapPath("~/FlexPaper/gif2swf.exe"); 8 9 10 public ActionResult Index(string filePath = "") 11 { 12 13 string msg = CreateSWF(filePath); 14 if (msg == "生成成功") 15 { 16 string FilePath = Server.MapPath(filePath); 17 string fileNameWithoutEx = System.IO.Path.GetFileNameWithoutExtension(FilePath);//不包含路径,不包含扩展名 18 string extendName = System.IO.Path.GetExtension(FilePath).ToLower();//文件扩展名 19 var sign = extendName.Replace(".", ""); 20 21 string url = "/FlexPaper/SWF/" + fileNameWithoutEx +sign+ ".swf"; 22 try 23 { 24 return Redirect(string.Format("/FlexPaper/FlexPaperViewer.html?emotion={0}", url)); 25 } 26 catch 27 { 28 return Content("转化失败,不支持该类型转化!"); 29 } 30 } 31 else 32 return Content(msg); 33 } 34 35 /// <summary> 36 /// 0:转化成功 37 /// 1:不支持的该Office文件类型到pdf的转化 38 /// 2:不支持的该文件类型到swf的转化 39 /// </summary> 40 /// <returns></returns> 41 public string CreateSWF(string filePath) 42 { 43 string FilePath = Server.MapPath(filePath); 44 int index = FilePath.LastIndexOf("\\"); 45 string officePath = FilePath.Substring(0, index)+"\\"; 46 string officeName = Server.UrlDecode(FilePath.Substring(index + 1)); 47 string fileNameWithoutEx = System.IO.Path.GetFileNameWithoutExtension(FilePath);//不包含路径,不包含扩展名 48 string extendName = System.IO.Path.GetExtension(FilePath).ToLower();//文件扩展名 49 string sign = extendName.Replace(".", ""); 50 string PdfFilePath = Server.MapPath("~/FlexPaper/PDF/"); 51 string SWFFilePath = Server.MapPath("~/FlexPaper/SWF/"); 52 53 54 #region delete old file 55 string oldPdf = PdfFilePath + fileNameWithoutEx + sign + ".pdf"; 56 if (System.IO.File.Exists(oldPdf)) 57 { 58 System.IO.File.Delete(oldPdf); 59 } 60 string oldSwf = SWFFilePath + fileNameWithoutEx + sign + ".swf"; 61 if (System.IO.File.Exists(oldSwf)) 62 { 63 System.IO.File.Delete(oldSwf); 64 } 65 #endregion 66 67 if (!System.IO.File.Exists(FilePath)) 68 { 69 return "找不到该文件!" ; 70 } 71 72 73 if (extendName == ".doc" || 74 extendName == ".docx" || 75 extendName == ".xls" || 76 extendName == ".ppt") 77 { 78 79 //string pdf2swfToolPath = string.Format("{0}\\pdf2swf.exe", Server.MapPath("~/FlexPaper")); 80 81 string PdfName = Utils.OfficeToPdf(officePath, officeName, PdfFilePath); 82 if (PdfName == "") 83 { 84 return "不支持该Office文件类型到pdf的转化!"; 85 } 86 string SwfName = Utils.PdfToSwf(pdf2swfToolPath, PdfFilePath, PdfName, SWFFilePath); 87 if (SwfName == "") 88 { 89 return "不支持该文件类型到swf的转化!"; 90 } 91 return "生成成功"; 92 } 93 else if (extendName == ".jpg" || extendName == ".jpeg" || extendName == ".png" || extendName == ".gif") 94 { 95 string toolpath = String.Empty; 96 switch (extendName) 97 { 98 case ".jpg": 99 toolpath = jpeg2swfToolPath; 100 break; 101 case ".jpeg": 102 toolpath = jpeg2swfToolPath; 103 break; 104 case ".png": 105 toolpath = png2swfToolPath; 106 break; 107 case ".gif": 108 toolpath = gif2swfToolPath; 109 break; 110 default: 111 break; 112 } 113 string SwfFileName = Utils.PictureToSwf(toolpath, officePath, officeName, SWFFilePath); 114 return "生成成功"; 115 } 116 else 117 return "不支持该文件类型的转化!"; 118 }
c.新建FlexPaper文件夹,在该文件夹下再另外创建PDF,SWF子文件夹,此处原创便于区分,另把从网上下载demo里的js,FlexPaperViewer.html,FlexPaperViewer.swf
playerProductInstall.swf文件都拷过去。
把Swftools安装路径下的工具pdf2swf.exe,也拷过去,如有需要,其他类型也可拷过去。
修改FlexPaperViewer.html便于传递文件名
<script type="text/javascript"> //获得参数的方法 var request = { QueryString: function (val) { var uri = window.location.search; var re = new RegExp("" + val + "=([^&?]*)", "ig"); return ((uri.match(re)) ? (uri.match(re)[0].substr(val.length + 1)) : null); } } </script> var emotion = request.QueryString('emotion'); ; //这填写文档转成的flash文件路径 var swfFile = emotion; var flashvars = { SwfFile: escape(swfFile),//这里用到swf路径 Scale : 0.6, ZoomTransition : "easeOut",
UploadFiles里添加需要在线预览的office文件。
3.最后一个坑
在本地调试没有问题,发布到IIS上后,一直加载中,无法正常显示,经查找测试发现是引用office组件的权限问题。
需要在Web.config里加一段代码:
<system.web> <identity impersonate="true" userName="你的用户名" password="密码"/>
4.预览效果