Extjs上传附件实战开发,实现批量上传及在线预览功能(三)

文档转换服务程序:

      1、安装软件openoffice

             下载最新版本3.4.1,及SDK3.4.1,openoffice默认安装在服务器上,SDK直接安装在开发本机上,安装后打开目录C:\Program Files\OpenOffice.org 3\Basis\sdk\cli

       复制文件夹里的5个文件即可:

Extjs上传附件实战开发,实现批量上传及在线预览功能(三)_第1张图片

     2、安装swftools-0.9.2

            直接安装在开发本机,复制安装目录的pdf2swf.exe程序即可。

     3、下载xpdf-chinese-simplified

            下载字体:gkai00mp.rar,修改xpdf-chinese-simplified目录下的add-to-xpdfrc文件。将里面的路径设为自己的路径:

#----- begin Chinese Simplified support package (2011-sep-02)
cidToUnicode Adobe-GB1    C:\xpdf-chinese-simplified\Adobe-GB1.cidToUnicode
unicodeMap   ISO-2022-CN C:\xpdf-chinese-simplified\ISO-2022-CN.unicodeMap
unicodeMap   EUC-CN         C:\xpdf-chinese-simplified\EUC-CN.unicodeMap
unicodeMap   GBK              C:\xpdf-chinese-simplified\GBK.unicodeMap
cMapDir        Adobe-GB1    C:\xpdf-chinese-simplified\CMap
toUnicodeDir                     C:\xpdf-chinese-simplified\CMap
fontDir                             C:\WINDOWS\Fonts
displayCIDFontTT Adobe-GB1 C:\xpdf-chinese-simplified\CMap\gkai00mp.ttf
#fontFileCC Adobe-GB1 /usr/..../gkai00mp.ttf
#----- end Chinese Simplified support package

          参照上面的代码,在调用pdf2swf命令中加入“ -s languagedir=D:\\xpdf\\xpdf-chinese-simplified ”参数。

          String cmd = exePath + " \"" + fileDir + "\" -o \"" + filePath + "/" + fileName + ".swf\" -T 9 -s languagedir=c:\\xpdf-chinese-simplified";

         这样乱码的问题就解决了。

      4、开发winform程序

             具体如何建项目不再阐述,笔者用的是VS2010,本程序工作流程:

            a、 定时器1定时读取数据库---获取需要转换的文档信息

            b、获取一次信息后,起动一个线程开始转换文档

            c、定时器2定时获取转换状态及转换服务起动状态

            d、定时器3定时记录转换用时

            从数据库加载数据到dataGridView上不再阐述,这里重点谈谈C#如果调用openoffice和pdf2swf.exe进行转换。

            首先定义全局变量:

//------------------------------
        public static string WebDirectory;//网站根目录 
        public static string PDFProcesses;//openoffice程序目录
        public static string LanguageDir;//xpdf-chinese-simplified目录
 //------------------------------
             新建该项目的App.config文件,内容如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>   
  </startup>
  <appSettings>
    <add key="AutoRun" value="true"/>
    <add key="ConnectionString" value=""/>
    <add key="WebDirectory" value="C:\WWW\"/>
    <add key="PDFProcesses" value="C:\Program Files\OpenOffice.org 3\program\soffice.exe"/>
    <add key="LanguageDir" value="C:\xpdf-chinese-simplified\"/>
  </appSettings>
</configuration>

           AutoRun为是否程序启动就进行转换; ConnectionString为数据库连接字符串,网站web.config中的是什么就复制什么。

<startup useLegacyV2RuntimeActivationPolicy="true">
    <supportedRuntime version="v4.0"/>   
  </startup>
         这个是必须的,否则无法启动openoffice程序,调试出错。

         这样在程序初始化中获取这些参数:

public Form1()
        {
            InitializeComponent();
            ld.ConnectionString = GetAppConfig("ConnectionString");
            WebDirectory = GetAppConfig("WebDirectory");
            PDFProcesses = GetAppConfig("PDFProcesses");
            LanguageDir = GetAppConfig("LanguageDir");
        }
public static string GetAppConfig(string AppKey)
        {
            try
            {
                string AppKeyValue;
                AppKeyValue = ConfigurationManager.AppSettings.Get(AppKey);
                return AppKeyValue;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

           新建ToPDF.cs文件,内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;
using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.bridge;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.text;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.sheet;
using unoidl.com.sun.star.container;
using unoidl.com.sun.star.table;
namespace ConvertPS
{
    class ToPDF
    {
        private static Mutex _openOfficeLock = new Mutex(false, "OpenOfficeMutexLock-MiloradCavic");
        string sourcePath, destinationPath;
        public ToPDF(string sPath, string dPath)
        {
            //
            // TODO: Add constructor logic here
            //     
            sourcePath = sPath;
            destinationPath = dPath;
        }
        /// <summary>
        /// Converts document to PDF
        /// </summary>
        /// <param name="sourcePath">Path to document to convert(e.g: C:\test.doc)</param>
        /// <param name="destinationPath">Path on which to save PDF (e.g: C:\test.pdf)</param>
        /// <returns>Path to destination file if operation is successful, or Exception text if it is not</returns>
        public void Generate()
        {
            bool obtained = _openOfficeLock.WaitOne(60 * 1000, false);
            XComponent xComponent = null;

            try
            {
                if (!obtained)
                {
                    throw new System.Exception(string.Format("Request for using OpenOffice wasn't served after {0} seconds. Aborting...", 30));
                }

                sourcePath = PathConverter(sourcePath);
                destinationPath = PathConverter(destinationPath);

                // 載入文件前屬性設定,設定文件開啟時隱藏  
                PropertyValue[] loadDesc = new PropertyValue[1];
                loadDesc[0] = new PropertyValue();
                loadDesc[0].Name = "Hidden";
                loadDesc[0].Value = new uno.Any(true);

                //Get a ComponentContext
                unoidl.com.sun.star.uno.XComponentContext xLocalContext = uno.util.Bootstrap.bootstrap();

                //Get MultiServiceFactory
                unoidl.com.sun.star.lang.XMultiServiceFactory xRemoteFactory = (unoidl.com.sun.star.lang.XMultiServiceFactory)xLocalContext.getServiceManager();

                //Get a CompontLoader
                XComponentLoader aLoader = (XComponentLoader)xRemoteFactory.createInstance("com.sun.star.frame.Desktop");

                //Load the sourcefile
                //xComponent = aLoader.loadComponentFromURL(sourcePath, "_blank", 0, new unoidl.com.sun.star.beans.PropertyValue[0]);
                xComponent = aLoader.loadComponentFromURL(sourcePath, "_blank", 0, loadDesc);
                //Wait for loading
                while (xComponent == null)
                {
                    System.Threading.Thread.Sleep(3000);
                }

                saveDocument(xComponent, destinationPath);

                xComponent.dispose();
                //return destinationPath;
            }
            catch (System.Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());
                //throw ex;
            }
            finally
            {
                Process[] pt = Process.GetProcessesByName("soffice.bin");
                if (pt != null && pt.Length > 0)
                    pt[0].Kill();

                Process[] ps = Process.GetProcessesByName(Form1.PDFProcesses);
                if (ps != null && ps.Length > 0)
                    ps[0].Kill();

                //if (System.IO.File.Exists(sourcePath))
                //    File.Delete(sourcePath);

                if (obtained)
                    _openOfficeLock.ReleaseMutex();
            }
        }


        /// <summary>
        /// Saves the document.
        /// </summary>
        /// <param name="xComponent">The x component.</param>
        /// <param name="fileName">Name of the file.</param>
        private static void saveDocument(XComponent xComponent, string fileName)
        {
            unoidl.com.sun.star.beans.PropertyValue[] propertyValue = new unoidl.com.sun.star.beans.PropertyValue[2];//[1];

            propertyValue[0] = new unoidl.com.sun.star.beans.PropertyValue();
            //propertyValue[0].Name = "FilterName";
            //propertyValue[0].Value = new uno.Any("writer_pdf_Export");
            propertyValue[0].Name = "Overwrite";
            propertyValue[0].Value = new uno.Any(true);
            // Setting the filter name
            propertyValue[1] = new PropertyValue();
            propertyValue[1].Name = "FilterName";
            propertyValue[1].Value = new uno.Any("writer_pdf_Export");

            ((XStorable)xComponent).storeToURL(fileName, propertyValue);
        }

        /// <summary>
        /// Convert into OO file format
        /// </summary>
        /// <param name="file">The file.</param>
        /// <returns>The converted file</returns>
        private static string PathConverter(string file)
        {
            try
            {
                file = file.Replace(@"\", "/");

                return "file:///" + file;
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }
    }
}

        这段代码源自某仁兄的OpenOfficeConvert实例,表示感谢,这里分析一下他的几个实例:

Extjs上传附件实战开发,实现批量上传及在线预览功能(三)_第2张图片

        笔者看完后分析得出,有两种转换方式:一种是调用SDK的库调用openoffice,一种是开启一个openoffice服务,连接服务进行转换(这种方法博客园有篇文章“仿百度文库方案【openoffice.org 3+swftools+flexpaper】”就是采用连接服务进行转换的方式,由于该方法后台采用的是java,而且用了JODConverter,JODConverter是一个java的OpenDucument文件转换器,可以进行许多文件格式的转换,它利用OpenOffice来进行转换工作,所以和asp.net一点关系也没有,未采用,如果读者感兴趣可参考该文进行实现)。本文采用第一种方法,在这里就需要引用刚才安装openofficeSDK的那5个包了,如果引用正确:

using unoidl.com.sun.star.lang;
using unoidl.com.sun.star.uno;
using unoidl.com.sun.star.bridge;
using unoidl.com.sun.star.frame;
using unoidl.com.sun.star.text;
using unoidl.com.sun.star.beans;
using unoidl.com.sun.star.sheet;
using unoidl.com.sun.star.container;
using unoidl.com.sun.star.table;

这里就没有问题了。

        说明:此ToPDF类在原来的基础上作了修改,解决了启动openoffice(虽然使用了hidden)会打开界面的问题,表现为打开后又关闭。其中传入参数sPath为需要转换的文档地址,dPath为存放的地址。

         新建ToSWF.cs文件,内容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace ConvertPS
{
    class ToSWF
    {
        Process p = new Process();
        public ToSWF(string cmdStr, string argsStr)
        {
            //
            // TODO: Add constructor logic here
            //
            ProcessStartInfo psi = new ProcessStartInfo(cmdStr, argsStr);
            psi.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo = psi;
            p.StartInfo.WorkingDirectory = Form1.WebDirectory + "SWFTools\\";

        }
        public void Running()
        {
            p.Start();
            p.WaitForExit();
            p.Close();//关闭进程
              p.Dispose();//释放资源

        }
    }
}

        这个就比较简单,cmdStr为pdf2swf.exe程序地址,argsStr 为启动参数,即argsStr="-t " + sourcePath1 + " -T 9 -s languagedir="+Form1.LanguageDir+" -o " + targetPath; sourcePath1 为需要转换的pdf地址,targetPath为存放地址。

        

注意事项:

        1、GetAppConfig(string AppKey)函数中用到了System.Configuration 命名空间,这个VS2010是不自带的,需要手动把System.configuration.dll文件放在bin-debug中。

        2、线程内一般是不能操作界面控件的,所以在转换线程内,首先需要读取dataGridView的一行数据,得到文档地址,再启动openoffice,pdf2swf.exe进行转换,转换完成后需要更新该行的转换状态,表示转换成功与否,如图:

Extjs上传附件实战开发,实现批量上传及在线预览功能(三)_第3张图片

         为了能够在线程内更新这些数据,必须使用容器来解决,将需要的数据存入容器,一般用变量,ArrayList,但这里有点特殊,更新的是表格的数据,而表格数据源用的是什么?是DataTable,笔者就用DataTable作这个容器,获取数据行就用:

DataTable dat;
s_guid = dat.Rows[k]["Guid"].ToString();
//设置也一样
dat.Rows[k]["ZT"] = "转换成功";

        而定时器2为了能够获取到正在转换的文档信息,故用ArrayList在线程内存入正在转换的文档信息。请注意ArrayList是可以存放任何类型的数据,一个数组也行。

       3、为实现该程序后台自动启动,定时器采用服务程序类定时器,添加该控件即可。

 

作者: kunoy
出处: http://blog.csdn.net/kunoy
申明:作者写博是为了总结经验,和交流学习之用。
如需转载,请尽量保留此申明,并在文章页面明显位置给出原文连接。谢谢!


 

你可能感兴趣的:(文件上传,ExtJs,批量,在线预览)