.net 在线预览文档非常全面的案例

前段时间项目有一个在线预览office文档的需求,做了一个小栗子,和大家一起学习学习!如何实现这个功能呢?我总结了几个方案:

方案一:将需要转换的文档通过office组件转换成html查看

方案二:将需要转换的文档通过office组件转换成pdf查看

方案三:通过在服务器部署微软的office web apps进行文档预览    参考网页:  https://www.cnblogs.com/yanweidie/p/4516164.html

方案四:office 在线预览服务

方案五:使用网上很多收费或者不收费的第三方插件

我使用的是方案一,也试过方案二和方案三,相比而言,转换成html比转换成pdf的效率要快很多,只是页面没有pdf美观,而在服务器部署office web apps配置失败了,所以选择放弃。

以下是方案一的案例:

1.首先引入com组件中office库,然后在程序集扩展中引入word的dll,我本来是想使用.net  core做这个在线预览offce文档,结果发现.net core 并没有office库,可能是我没有找到

 

 

 值得注意的是,虽然项目里引入office库,但运行项目后,发现会遇到各种问题,原因是office库并没有你电脑的office应用匹配,所以需要在电脑需要部署office插件

1.运行栏中输入命令:dcomcnfg,打开组件服务管理窗口,组件服务->我的电脑->DCOM配置
2.找到Microsoft Excel Application 设置属性标识:交互式用户,在安全了的三个配置全选自定义配置,添加Everyone 组,给这个组的权限都勾选未允许,
3.再找到 Microsoft PowerPoint 幻灯片  权限设置和第二步一样
4.再找到Microsoft Word 97 - 2003 文档 权限设置和第二步一样  (可能office版本不同)
5.在项目的webconfig  里   <system.web> 下 添加   <identity impersonate="true" userName="Administrator" password="123456"/>  userName、password为服务器的对应账号密码

查了很多资料,亲测可用  参考网页:https://www.cnblogs.com/5426z/articles/4865312.html

2.预览Excel

        /// 预览Excel
        /// </summary>
        /// <param name="physicalPath">解码的地址</param>
        /// <param name="url"></param>
        public string PreviewExcel(string physicalPath, string url)
        {
            var resultUrl = string.Empty;
            var serverUrl = string.Empty;
            try
            {
                Microsoft.Office.Interop.Excel.Application application = null;
                //参数
                Workbook workbook = null;
                application = new Microsoft.Office.Interop.Excel.Application();
                object missing = Type.Missing;
                object trueObject = true;
                application.Visible = false;
                application.DisplayAlerts = false;
                workbook = application.Workbooks.Open(physicalPath, missing, trueObject, missing, missing, missing,
                   missing, missing, missing, missing, missing, missing, missing, missing, missing);
                object format = XlFileFormat.xlHtml;
                string htmlName = Path.GetFileNameWithoutExtension(physicalPath) + ".html";
                String outputFile = Path.GetDirectoryName(physicalPath) + "\\" + htmlName;
                workbook.SaveAs(outputFile, XlFileFormat.xlHtml, null, null, false, false,
                   XlSaveAsAccessMode.xlNoChange, null, null, null, null, null);

                workbook.Close();
                application.Quit();
                resultUrl = Path.GetDirectoryName(url) + "\\" + htmlName;
                var lastUrl = Path.GetFileName(resultUrl);
                resultUrl = ConfigurationManager.AppSettings["ResultUrl"] + lastUrl;
                serverUrl = ConfigurationManager.AppSettings["ServerUrl"];
            }
            catch (Exception ex)
            {
                this.Write(ex);
            }
            return serverUrl + resultUrl;
}

 

4.预览Word

        /// 预览Word(HtmL类型)
        /// </summary>
        /// <param name="physicalPath"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public string PreviewWord(string physicalPath, string url)
        {

            var resultUrl = string.Empty;
            var serverUrl = string.Empty;
            object outputFile1 = new object();
            object missing1 = new object();
            //检查doc 是否被实例化
            var idd = 0;
            var ss = 1;
            try
            {
                Microsoft.Office.Interop.Word._Application application = null;
                Microsoft.Office.Interop.Word._Document doc = null;
                application = new Microsoft.Office.Interop.Word.Application();
                //参数
                object missing = Missing.Value;
                object trueObject = true;
                application.Visible = false;
                application.DisplayAlerts = WdAlertLevel.wdAlertsNone;
                object physicalPathObj = physicalPath;
                //实例化
                doc = application.Documents.Open(ref physicalPathObj, ref missing, ref trueObject, ref missing, ref missing, ref missing,
                 ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing, ref missing);
                string htmlName = Path.GetFileNameWithoutExtension(physicalPath) + ".html";
                object outputFile = Path.GetDirectoryName(physicalPath) + "\\" + htmlName;
                object format = WdSaveFormat.wdFormatHTML;
                outputFile1 = outputFile;
                missing1 = missing;
                idd = doc.DocID;
                ss = doc.CompatibilityMode;
                //转换并保存
                doc.SaveAs(ref outputFile, ref format, ref missing, ref missing, ref missing,
                                  ref missing, XlSaveAsAccessMode.xlNoChange, ref missing,
                                  ref missing, ref missing, ref missing, ref missing);
                doc.Close();
                application.Quit();
                //返回137的路径

                resultUrl = Path.GetDirectoryName(url) + "\\" + htmlName;
                var lastUrl = Path.GetFileName(resultUrl);
                resultUrl = ConfigurationManager.AppSettings["ResultUrl"] + lastUrl;
                serverUrl = ConfigurationManager.AppSettings["ServerUrl"];
            }
            catch (Exception ex)
            {
                this.Write(ex, $"{outputFile1}+{missing1}+{idd.ToString()}+{ss.ToString()}+{physicalPath}");

            }
            return serverUrl + resultUrl;
}

5.预览ppt,我使用的是Presentation库

    #region  预览ppt(使用Presentation插件)
        /// <summary>
        /// ppt转html
        /// </summary>
        /// <returns></returns>
        public string PptToHtml(string url)
        {
            var resultUrl = string.Empty;
            var serverUrl = string.Empty;
            string htmlName = Path.GetFileNameWithoutExtension(url) + ".html";
            String outputFile = Path.GetDirectoryName(url) + "\\" + htmlName;
            //实例化Presentation类,加载文件
            Spire.Presentation.Presentation ppt = new Spire.Presentation.Presentation();
            try
            {
                //打开文件
                ppt.LoadFromFile(url);
                //保存文件为HTML
                ppt.SaveToFile(outputFile, FileFormat.Html);
            }
            catch (Exception ex)
            {
                this.Write(ex);
            }
            //得到返回的html地址
            resultUrl = Path.GetDirectoryName(url) + "\\" + htmlName;
            var lastUrl = Path.GetFileName(resultUrl);
            resultUrl = ConfigurationManager.AppSettings["ResultUrl"] + lastUrl;
            serverUrl = ConfigurationManager.AppSettings["ServerUrl"];
            return serverUrl + resultUrl;


        }

6.将需要预览的文档转换成html流后下载到服务器,进行预览,因为浏览器不支持预览本地的文件。

 #region  Http下载文件
        /// <summary>
        /// Http下载文件(返回保存路劲)
        /// </summary>
        /// <param name="url">下载的oss路径</param>
        public async Task<Result> HttpDownloadFile(string url)
        {
            var result = new Result();
            var urlSpilt = string.Empty;
            var dataNow = DateTime.Now.ToString("yyyyMMddHHmmssfff");
            if (url.IndexOf('?') > 0)
                urlSpilt = url.Substring(0, url.IndexOf('?'));
            var urlStr = Path.GetFileName(urlSpilt);
            var key = ConfigurationManager.AppSettings["UrlKey"];
            //路径
            string path = key + dataNow + urlStr;
            try
            {
                // 设置参数
                HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
                //发送请求并获取相应回应数据
                HttpWebResponse response = request.GetResponse() as HttpWebResponse;
                //直到request.GetResponse()程序才开始向目标网页发送Post请求
                Stream responseStream = response.GetResponseStream();
                //创建本地文件写入流
                Stream stream = new FileStream(path, FileMode.Create);
                byte[] bArr = new byte[1024];
                int size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
                while (size > 0)
                {
                    stream.Write(bArr, 0, size);
                    size = await responseStream.ReadAsync(bArr, 0, (int)bArr.Length);
                }
                stream.Close();
                responseStream.Close();
                result.Url = path;
                result.IsSuccure = true;
            }
            catch (Exception ex)
            {
                this.Write(ex);
                result.IsSuccure = false;
                result.Message = "操作失败,请检查文件路径及文件格式是否正确";
            }
            return result;
        }
        #endregion

7.错误日志

        /// 错误日志
        /// </summary>
        /// <param name="ex"></param>
        /// <param name="message">打印其他信息,看插件是否实例化</param>
        public void Write(Exception ex, string message = "")
        {
            var SaveKey = ConfigurationManager.AppSettings["UrlKey"];
            string filePath = SaveKey + DateTime.Now.ToString("yyyyMMddHHmmss") + ".txt";
            FileStream fs = System.IO.File.Create(filePath);
            StreamWriter sw = new StreamWriter(fs);
            //开始写入
            sw.WriteLine("异常信息=" + ex.Message);
            sw.WriteLine(ex.StackTrace);
            sw.WriteLine($"自定义消息:{message}");
            //清空缓冲区
            sw.Flush();
            //关闭流
            sw.Close();
            fs.Close();
        }

8.返回在服务器上已经转换成功的html文件路径

        /// 返回最终结果的html
        /// </summary>
        /// <param name="url">oss路径</param>
        public async Task<Result> GetResultUrl(string url)
        {
            var SaveKey = ConfigurationManager.AppSettings["UrlKey"];
            Result result = new Result();
            Helper helper = new Helper();
            try
            {
                string physicalPath = Server.UrlDecode(url);
                //去除url后的参数
                if (physicalPath.IndexOf('?') > 0)
                    physicalPath = physicalPath.Substring(0, physicalPath.IndexOf('?'));
                string extension = Path.GetExtension(physicalPath);
                switch (extension.ToLower())
                {
                    case ".xls":
                    case ".xlsx":
                        var resultPathExel = await helper.HttpDownloadFile(url);
                        if (resultPathExel != null && !resultPathExel.IsSuccure)
                        {
                            result.IsSuccure = false;
                            result.Message = resultPathExel.Message;
                            return result;
                        }
                        //转换成html流
                        string physicalPath1 = Server.UrlDecode(resultPathExel.Url);
                        result.Url =  helper.PreviewExcel(physicalPath1, resultPathExel.Url);
                        result.State = (int)Etype.Html;
                        result.IsSuccure = true;
                        break;
                    case ".doc":
                    case ".docx":
                        var resultPathWord = await helper.HttpDownloadFile(url);
                        if (resultPathWord != null && !resultPathWord.IsSuccure)
                        {
                            result.IsSuccure = false;
                            result.Message = resultPathWord.Message;
                            return result;
                        }
                        //转换成html流
                        string physicalPath2 = Server.UrlDecode(resultPathWord.Url);
                        result.Url = helper.PreviewWord(physicalPath2, resultPathWord.Url);
                        result.State = (int)Etype.Html;
                        result.IsSuccure = true;
                        break;
                    case ".ppt":
                    case ".pptx":
                        var resultPathPPT = await helper.HttpDownloadFile(url);
                        if (resultPathPPT != null && !resultPathPPT.IsSuccure)
                        {
                            result.IsSuccure = false;
                            result.Message = resultPathPPT.Message;
                            return result;
                        }
                        string physicalPath3 = Server.UrlDecode(resultPathPPT.Url);
                        result.Url =  helper.PptToHtml(physicalPath3);
                        result.State = (int)Etype.Html;
                        result.IsSuccure = true;
                        break;
                    case ".txt":
                        result.Url = url;
                        result.State = (int)Etype.Html;
                        result.IsSuccure = true;
                        break;
                    case ".pdf":
                        var resultFile = await helper.HttpDownloadFile(url);
                        if (resultFile != null && !resultFile.IsSuccure)
                        {
                            result.IsSuccure = false;
                            result.Message = resultFile.Message;
                            return result;
                        }
                        //截取web后的地址
                        var urlStr = Path.GetFileName(resultFile.Url);
                        result.Url = urlStr;
                        result.State = (int)Etype.pdf;
                        result.IsSuccure = true;
                        break;
                    case ".jpg":
                    case ".jpeg":
                    case ".bmp":
                    case ".gif":
                    case ".png":
                        result.Url = url;
                        result.State = (int)Etype.Html;
                        result.IsSuccure = true;
                        break;
                    default:
                        result.Url = url;
                        result.State = (int)Etype.other;
                        result.IsSuccure = true;
                        break;
                }
            }
            catch (Exception ex)
            {
                helper.Write(ex);
            }
return result; }

9.在页面预览

        /// 首页
        /// </summary>
        /// <param name="fileurl">文件网络地址</param>
        /// <returns></returns>
        public async Task<ActionResult> Index(string fileurl)
        {
            Helper helper = new Helper();
            var serverUrl = ConfigurationManager.AppSettings["ServerUrl"];
            string viewUrl = string.Empty;
            var result = new Result();
            if (string.IsNullOrEmpty(fileurl))
            {
                result.IsSuccure = false;
                result.Message = "请输入需要预览的文件地址";
                return Json(result, JsonRequestBehavior.AllowGet);
            }
            //压缩包提示解压
            if (fileurl.IndexOf('?') > 0)
                fileurl = fileurl.Substring(0, fileurl.IndexOf('?'));
            string extension = Path.GetExtension(fileurl);
            if (extension == ".zip")
            {
                result.IsSuccure = false;
                result.Message = "不能预览压缩包文件,请解压后查看";
                return Json(result, JsonRequestBehavior.AllowGet);
            }//得到最终链接地址
            result = await GetResultUrl(fileurl);
            if (result.IsSuccure)
            {
                if (result.State == (int)Etype.Html)
                    Response.Redirect(result.Url.ToString());
                if (result.State == (int)Etype.pdf)
                    //pdf.js固定的位置
                    Response.Redirect($"{serverUrl}Content/web/viewer.html?file=Files/{ result.Url}");
            }
            return View(result);
        }

 

写在最后的话:

虽然pdf文件可以在谷歌内核打开,但是其他的浏览器是不可以 的比如QQ浏览器,同时我也需要兼容手机端,所以我吧谷歌使用的pdf.js插件搞了过来,大家可以学习一下这个插件,将这个插件部署在自己的项目中,就拥有了谷歌同样预览pdf文件的功能了。

参考资料:https://blog.csdn.net/AresonZ/article/details/81873509

这个小栗子的弊端是不能很多个文件同时预览,会很耗服务器资源,后来我进行了优化,加了冥等性和锁,同时也加了多线程。总之,第一次写博客,和大家交流学习一下,有什么不对的地方希望大家指出。

 

posted on 2019-10-16 11:09  晚照对晴空  阅读(1796)  评论(0编辑  收藏  举报

导航