Asp.Net使用FlexPaper开发文库功能

作者:陆金龙    发表时间:2014-11-15 20:09   


文库功能的基本思路是在管理页面提供一个文件上传功能,并将上传的文件在服务端转换得到相应的swf格式文件。在数据库中记录文件的名称,相对路径信息。在文档浏览页面,从数据库查询到需要展示文档的swf格式文件存放路径,通过FlexPaper进行在线浏览展示。

本文主要从开发环境的安装、功能代码实现、服务器部署及配置这几个方面,分享Office文档到swf格式的转换,及使用FlexPaper进行文档在线浏览的实现。

由于文档的上传功能不是本文的重点,其具体实现不在这里讨论。本站文库功能的效果展示:http://iprogram.com.cn/FlexPaper.htm?articleId=16

一、开发运行环境安装

1.安装完整版Office2007

卸载干净WPS、Office2003等产品,重新安装Microsoft Office2007

如果已安装Office2007是简化版,请卸载重新安装Office2007完整版本,并进行授权许可激活。

Office2007可以直接将文档保存为PDF格式。不过需要安装一个微软提供的加载项。

2.安装转pdf加载项

下载安装支持Office转pdf的加载项:SaveAsPDFandXPS.exe。

下载地址:

http://www.microsoft.com/downloads/details.aspx?FamilyId=4D951911-3E7E-4AE6-B059-A2E79ED87041&displaylang=zh-cn

3.安装Pdf虚拟打印机

安装Pdf虚拟打印机软件 Adobe_PDF_Printer。

下载地址:http://www.cr173.com/soft/42951.html

4.安装pdf转swf工具

安装pdf转swf软件:swftools-0.9.0.exe

下载地址:http://www.swftools.org/download.html

二、项目添加程序集引用

1.程序集引用到项目

在项目引用中右击选择添加引用,添加.net中以下项,注意如果使用Office2007,对应程序集的版本为12.0.0.0。

Microsoft.Office.Interop.Word; 

Microsoft.Office.Interop.Excel;

Microsoft.Office.Interop.PowerPoint;

 

在项目引用中右击选择添加引用,在COM里面选择以下项:

Microft Office 12.0 object Library

 

2.为引用的类库设置属性

项目生成时可能报类似如下的错误:无法嵌入互操作类型“Microsoft.Office.Interop.Excel.ApplicationClass”。请改用适用的接口。

解决以上报错,需在引用文件夹下依次为Microsoft.Office.Interop.Word、Microsoft.Office.Interop.Excel、Microsoft.Office.Interop.PowerPoint按如下方式设置属性。

                  

三、文档格式转换功能代码

以下是文档格式有Office转换为Swf格式的2个类文件的代码。可以在文库项目的上传功能中调用其中的方法将Office文档先转为pdf格式,然后转为swf格式。文库浏览时需要用到swf格式的文件。

1.Office转Pdf功能代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using Word = Microsoft.Office.Interop.Word;

using Excel = Microsoft.Office.Interop.Excel;

using PowerPoint = Microsoft.Office.Interop.PowerPoint;

using Microsoft.Office.Core;

using System.IO;

namespace Wenku

{

    /// <summary>

    /// Office2Pdf 将Office文档转化为pdf

    /// </summary>

    public class Office2Pdf

    {

        public Office2Pdf()

        {

        }

        /// <summary>

        /// Word转换成pdf

        /// </summary>

        /// <param name="sourcePath">源文件路径</param>

        /// <param name="targetPath">目标文件路径</param>

        /// <returns>true转换成功</returns>

        public bool DOCConvertToPDF(string sourcePath, string targetPath)

        {

            bool result = false;

            Word.WdExportFormat exportFormat = Word.WdExportFormat.wdExportFormatPDF;

            object paramMissing = Type.Missing;

            Word.ApplicationClass wordApplication = new Word.ApplicationClass();

            Word.Document wordDocument = null;

            try

            {

                object paramSourceDocPath = sourcePath;

                string paramExportFilePath = targetPath;

                Word.WdExportFormat paramExportFormat = exportFormat;

                bool paramOpenAfterExport = false;

                Word.WdExportOptimizeFor paramExportOptimizeFor = Word.WdExportOptimizeFor.wdExportOptimizeForPrint;

                Word.WdExportRange paramExportRange = Word.WdExportRange.wdExportAllDocument;

                int paramStartPage = 0;

                int paramEndPage = 0;

                Word.WdExportItem paramExportItem = Word.WdExportItem.wdExportDocumentContent;

                bool paramIncludeDocProps = true;

                bool paramKeepIRM = true;

                Word.WdExportCreateBookmarks paramCreateBookmarks = Word.WdExportCreateBookmarks.wdExportCreateWordBookmarks;

                bool paramDocStructureTags = true;

                bool paramBitmapMissingFonts = true;

                bool paramUseISO19005_1 = false;

                wordDocument = wordApplication.Documents.Open(

                    ref paramSourceDocPath, ref paramMissing, ref paramMissing,

                    ref paramMissing, ref paramMissing, ref paramMissing,

                    ref paramMissing, ref paramMissing, ref paramMissing,

                    ref paramMissing, ref paramMissing, ref paramMissing,

                    ref paramMissing, ref paramMissing, ref paramMissing,

                    ref paramMissing);

                if (wordDocument != null)

                    wordDocument.ExportAsFixedFormat(paramExportFilePath,

                        paramExportFormat, paramOpenAfterExport,

                        paramExportOptimizeFor, paramExportRange, paramStartPage,

                        paramEndPage, paramExportItem, paramIncludeDocProps,

                        paramKeepIRM, paramCreateBookmarks, paramDocStructureTags,

                        paramBitmapMissingFonts, paramUseISO19005_1,

                        ref paramMissing);

                result = true;

            }

            catch(Exception ex)

            {

                File.AppendAllText(@"c:\log.txt", ex.Message + "\r\n" + ex.StackTrace.ToString());

            }

            finally

            {

                if (wordDocument != null)

                {

                    wordDocument.Close(ref paramMissing, ref paramMissing, ref paramMissing);

                    wordDocument = null;

                }

                if (wordApplication != null)

                {

                    wordApplication.Quit(ref paramMissing, ref paramMissing, ref paramMissing);

                    wordApplication = null;

                }

                GC.Collect();

                GC.WaitForPendingFinalizers();

                GC.Collect();

                GC.WaitForPendingFinalizers();

            }

            return result;

        }

 

        /// <summary>

        /// 把Excel文件转换成PDF格式文件  

        /// </summary>

        /// <param name="sourcePath">源文件路径</param>

        /// <param name="targetPath">目标文件路径</param>

        /// <returns>true转换成功</returns>

        public bool XLSConvertToPDF(string sourcePath, string targetPath)

        {

            bool result = false;

            Excel.XlFixedFormatType targetType = Excel.XlFixedFormatType.xlTypePDF;

            object missing = Type.Missing;

            Excel.ApplicationClass application = null;

            Excel.Workbook workBook = null;

            try

            {

                application = new Excel.ApplicationClass();

                object target = targetPath;

                object type = targetType;

                workBook = application.Workbooks.Open(sourcePath, missing, missing, missing, missing, missing,

                    missing, missing, missing, missing, missing, missing, missing, missing, missing);

                workBook.ExportAsFixedFormat(targetType, target, Excel.XlFixedFormatQuality.xlQualityStandard, true, false, missing, missing, missing, missing);

                result = true;

            }

            catch

            {

                result = false;

            }

            finally

            {

                if (workBook != null)

                {

                    workBook.Close(true, missing, missing);

                    workBook = null;

                }

                if (application != null)

                {

                    application.Quit();

                    application = null;

                }

                GC.Collect();

                GC.WaitForPendingFinalizers();

                GC.Collect();

                GC.WaitForPendingFinalizers();

            }

            return result;

        }

        

        ///<summary>        

        /// 把PowerPoint文件转换成PDF格式文件       

        ///</summary>        

        ///<param name="sourcePath">源文件路径</param>     

        ///<param name="targetPath">目标文件路径</param> 

        ///<returns>true转换成功</returns> 

        public bool PPTConvertToPDF(string sourcePath, string targetPath)

        {

            bool result;

            PowerPoint.PpSaveAsFileType targetFileType = PowerPoint.PpSaveAsFileType.ppSaveAsPDF;

            object missing = Type.Missing;

            PowerPoint.ApplicationClass application = null;

            PowerPoint.Presentation persentation = null;

            try

            {

                application = new PowerPoint.ApplicationClass();

                persentation = application.Presentations.Open(sourcePath, MsoTriState.msoTrue, MsoTriState.msoFalse, MsoTriState.msoFalse); persentation.SaveAs(targetPath, targetFileType, Microsoft.Office.Core.MsoTriState.msoTrue);

                result = true;

            }

            catch

            {

                result = false;

            }

            finally

            {

                if (persentation != null)

                {

                    persentation.Close();

                    persentation = null;

                }

                if (application != null)

                {

                    application.Quit();

                    application = null;

                }

                GC.Collect();

                GC.WaitForPendingFinalizers();

                GC.Collect();

                GC.WaitForPendingFinalizers();

            }

            return result;

        }

    }

}

 

2.Pdf转Swf功能代码

using System;

using System.Collections.Generic;

using System.Linq;

using System.Web;

using System.Diagnostics;

namespace Wenku

{

    /// <summary>

    /// Pdf2Swf 将pdf转化为swf

    /// </summary>

    public class Pdf2Swf

    {

        string cmdStr;

        public Pdf2Swf()

        {

        }

 

        public Pdf2Swf(string cmdStr)

        {

            this.cmdStr = cmdStr;

        }

 

        public void PdfConvert2Swf(string sourcePath, string targetPath)

        {

            if (string.IsNullOrEmpty(cmdStr))

            {

                cmdStr = "C:\\Program Files\\SWFTools\\pdf2swf.exe";

                //cmdStr = "C:\\Program Files(x86)\\SWFTools\\pdf2swf.exe";//windows 64位系统

            }

            string args = "  -t " + sourcePath + "  -o " + targetPath;

            ExecutCmd(cmdStr, args);

        }

 

        public static void ExecutCmd(string cmd, string args)

        {

            using (Process p = new Process())

            {

                p.StartInfo.FileName = cmd;

                p.StartInfo.Arguments = args;

                p.StartInfo.UseShellExecute = false;

                p.StartInfo.RedirectStandardOutput = false;

                p.StartInfo.CreateNoWindow = true;

                p.Start();

                p.PriorityClass = ProcessPriorityClass.Normal;

                p.WaitForExit();

            }

        }

}

}

 

四、文档在线浏览功能开发

1.下载flexpaper

从官网地址:http://flexpaper.devaldi.com/download/ 下载FlexPaper_2.2.4压缩包,包含了flexpaper及开发文档。

2.引用FlexPaper

解压下载好的压缩包,从FlexPaper_2.2.4目录下拷贝js文件夹和FlexPaperViewer.swf文件到项目中,如下图所示。

3.文档在线浏览功能代码

详细可参考FlexPaper_2.2.4中的index.htm中的示例。以下是一个简单的例子:

(1)添加测试页面FlexPaperDemo.htm,如上图所示将jquery.min.js,flexpaper.js,flexpaper_handlers.js这3个js库引用到页面。

(2)在body中添加 id="documentViewer" class="flexpaper_viewer"的div元素,文档将在这个层中展示。

(3)在$(function(){})中使用$('#documentViewer').FlexPaperViewer()函数实现在线文档浏览功能。其中,swfPath 变量是有Office文档转换后的swf格式文件相对与网站的路径。

 

完整页面代码如下:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head runat="server">

    <title>FlexPaper在线文档浏览测试</title>    

    <script type="text/javascript" src="js/jquery.min.js"></script>

    <script type="text/javascript" src="js/flexpaper.js"></script>

    <script type="text/javascript" src="js/flexpaper_handlers.js"></script>

    <script type="text/javascript">

        $(function () {

            var swfPath = "Upload/Attachements/2014/11/9/F3915E7B1D9F8E5C086501397FEDBA08.swf";

            if (swfPath != "") {

                $('#documentViewer').FlexPaperViewer(

                { config: {

                    SWFFile: swfPath,

                    Scale: 1.3,

                    ZoomTransition: 'easeOut',

                    ZoomTime: 1.5,

                    ZoomInterval: 0.2,

                    //FitPageOnLoad: true,

                    FitPageOnLoad: false,

                    FitWidthOnLoad: false,

                    FullScreenAsMaxWindow: false,

                    ProgressiveLoading: false,

                    MinZoomSize: 0.2,

                    MaxZoomSize: 5,

                    SearchMatchAll: false,

                    InitViewMode: 'Portrait',

                    RenderingOrder: 'flash',

                    StartAtPage: '',

 

                    ViewModeToolsVisible: true,

                    ZoomToolsVisible: true,

                    NavToolsVisible: true,

                    CursorToolsVisible: true,

                    SearchToolsVisible: true,

                    WMode: 'window',

                    localeChain: 'en_US'

                }

                });

            }

            else {

                $("documentViewer").text("附件不存在!");

            }

        });

    </script>

</head>

<body>

    <div id="documentViewer" class="flexpaper_viewer" style="width: 845px; height: 590px">

    </div>

</body>

</html>

五、部署到服务器的报错处理

项目开发完成后,在VS环境下运行通过,但是部署到服务器后,在文档格式转换部分出现以下报错信息。以下的报错信息是在将Word文档转为Pdf时发生的。Excel和PowerPoint的相关报错可以参照以下方案进行处理。

1.拒绝访问错误

报错信息:

Retrieving the COM class factory for component with CLSID {000209FF-0000-0000-C000-000000000046} failed due to the following error: 80070005 拒绝访问。 

To grant ASP.NET access to a file, right-click the file in Explorer, choose "Properties" and select the Security tab. Click "Add" to add the appropriate user or group. Highlight the ASP.NET account, and check the boxes for the desired Access.

解决方案:

在项目的web.config文件中添加配置项: <identity impersonate="true" userName="username" password="password"/>(这里的用户名和密码使用有管理员权限的系统登录账户和密码)。

2.加载类型库出错

报错信息:

添加上述配置后,上述报错解决,但是报以下错误:

Unable to cast COM object of type 'Microsoft.Office.Interop.Word.ApplicationClass' to interface type 'Microsoft.Office.Interop.Word._Application'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{000209FF-0000-0000-C000-000000000046}' failed due to the following error: 加载类型库/DLL 时出错。 (Exception from HRESULT: 0x80029C4A (TYPE_E_CANTLOADLIBRARY)). 

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

解决方案:

(1)修改注册表

运行->regedit打开注册表。找到HKEY_CLASSES_ROOT\AppID\MSACCESS.EXE的APPID,如果APPID的值与报错信息中的000209FF-0000-0000-C000-000000000046不一致,修改为000209FF-0000-0000-C000-000000000046。

(2)DCOM配置的“安全”设置

开始-运行中输入 DCOMCNFG或comexp.msc -32 (64位操作系统中使用comexp.msc -32 ),展开DCOM配置,找到Microsoft Office Word 97-2003文档,右键菜单点击属性打开对话框,点击"安全"标签。做如下配置:

(A)在"启动和激活权限"上点击"自定义",然后点击"编辑"。在弹出的对话框中填加一个"NETWORK SERVICE"、"EveryOne"用户(注意要选择本计算机名),并给它赋予"本地启动"和"本地激活"权限。添加ASPNET,并赋予所有的权限。

(B)在"访问权限"上点击"自定义",然后点击"编辑"。在弹出的对话框中也填加一个"NETWORK SERVICE"、"EveryOne"用户,然后赋予"本地访问"权限。

(C)在"配置权限"上点击"自定义,然后点击"编辑"。在编辑窗体中,添加ASPNET,并加入所有的权限。

(3) DCOM配置的“标识”设置

点击"标识"标签,选择“下列用户”,输入管理员帐号的用户名和密码。(网上有说设置为“交互性用户”的,在Winsows7系统中这样配置,确实有测试通过。不过我在一台Windows Server 2003服务器中只有采用“下列用户”时测试才通过)。

3.导出失败错误

    以下报错信息可能是因为本人的系统环境开始没有安装Pdf虚拟打印机,且安装的Office2007不是完整版的。如果在开发调试之前正确完整的安装好本文开头安装运行环境列出的4个软件,应该不会出现这个错误。

报错信息:

“由于出现意外错误,导出失败。”

   At Microsoft.Office.Interop.Word.DocumentClass.ExportAsFixedFormat(String OutputFileName, WdExportFormat ExportFormat, Boolean OpenAfterExport, WdExportOptimizeFor OptimizeFor, WdExportRange Range, Int32 From, Int32 To, 

WdExportItem Item, Boolean IncludeDocProps, Boolean KeepIRM, WdExportCreateBookmarks CreateBookmarks, Boolean DocStructureTags, Boolean BitmapMissingFonts, Boolean UseISO19005_1, Object& FixedFormatExtClassPtr)

分析测试:

出现以上报错,说明权限方面的配置已经通过了,这里是在执行Microsoft.Office.Interop.Word.DocumentClass.ExportAsFixedFormat进行文档格式转换时出现异常。

为了验证这个判断,直接用Office Word打开一个文档,另存为Pdf格式时,确实报同一个错误。

网上搜索的建议是安装PDF虚拟打印机程序。

解决方案:

   (1)下载安装一个PDF虚拟打印机小程序Adobe_PDF_Printer7.exe,在word2007里用虚拟打印的方法另存为PDF文件。还是报错。

   (2)考虑到原来安装的Office2007是简化版的,且安装了WPS,于是卸载干净WPS、Office,重装Office 2007 。此时打开Word文档另存为pdf成功。

   (3)运行程序时又报Unable to cast COM object of type 'Microsoft.Office.Interop.Word.ApplicationClass' 异常,检查注册表信息,原来HKEY_CLASSES_ROOT\AppID\MSACCESS.EXE的APPID在重装Office后又变回了00020906-0000-0000-C000-000000000046,改为000209FF-0000-0000-C000-000000000046,问题解决。

(转载本文请注明作者和原文链接 ,请勿用于任何商业用途)