zoukankan      html  css  js  c++  java
  • 知识管理系统Data Solution研发日记之三 文档解决方案

    前面两篇文章已经展示了Data Solution的设计目标和为达到此目标而设计的应用程序,这一篇继续细化对它的介绍,讲解Data Solution如何对文件进行扫描,转换,存储,检索。

    本机磁盘的文件格式通常是doc/docx,pdf,pst/ost/eml,htm/mht,txt/rtf,这几种格式是电脑中常用的格式。要达到在同一个编辑器Editor中可以对它们进行编辑,再整理,需要选择一种通用的格式,把其它的格式转化为这种通用格式,对这种格式进行编辑。DOC/DOCX格式功能强大,有很多开源类型库对它进行读写,RTF格式也包含了丰富数据资料,重要的一点是RTF格式,是一种开放的格式。可以到微软的网站上下载《Microsoft Office Word 2003 Rich Text Format (RTF) Specification》,以熟悉这种文件格式。开放格式的好处之一是,在后续的进一步开发中,可以找到很多现有的功能和代码,包括开放的源码。所以,Data Solution选择RTF格式作为文件存储的标准格式。

    下一个目标就是要找到RTF格式的编辑工具,通过Google可以找到很多RTF格式的编辑器,对RTF格式进行直接编辑,存储和转换。因为是开放格式,微软的.NET Framework自带了RichTextBox,可用于RTF格式的编辑。不过,这个控件还需要强化,可以到CodeProject.com上找到一些工具和文章。

    image

    这两个关键的步骤解决了,下面就是设计数据库和设计数据读写代码。创建Document数据库,文档表的脚本如下

    CREATE TABLE [dbo].[DOCUMENT](
        [RECNUM] [int] IDENTITY(1,1) NOT NULL,
        [SUBJECT] [nvarchar](2000) NULL,
        [BODY_TYPE] [nvarchar](50) NULL,
        [BODY] [nvarchar](max) NULL,
        [CREATE_DATE] [datetime] NULL,
        [CREATE_BY] [nvarchar](50) NULL,
        [REVISED_Date] [datetime] NULL,
        [REVISED_BY] [nvarchar](50) NULL,
        [CATEGORY] [int] NULL,    
        [COMPUTER] [nvarchar](200) NULL,
        [PATH] [nvarchar](2000) NULL,
     CONSTRAINT [PK_DOCUMENT] PRIMARY KEY CLUSTERED 
    (
        [RECNUM] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    Body就是存储文档的表字段,设计它为NVARCHAR(MAX)类型,CATEGORY用于文档的分类查找,SUBJECT可存放关键字或是标题,BODY_TYPE用于全文搜索,存储文档类型扩展名。COMPUTER和PATH用于在本机扫描中,指定原始文档的路径,可用于追踪。

    Data Solution系统选择LLBL Gen Framework作为数据库访问层的代码生成器,生成解决方案的代码如下图

    image

    来看一下,对文档进行保存的一段代码,它是标准的LLBL Gen Framework的routine代码

    public DocumentEntity SaveDocument(DocumentEntity doc)
    {
                using (DataAccessAdapter adapter = GetDataAccessAdapter())
                {
                    try
                    {
                        adapter.StartTransaction(IsolationLevel.ReadCommitted, "SaveDocument");
                        adapter.SaveEntity(doc, true, false);
                        adapter.Commit();
                    }
                    catch
                    {
                        adapter.Rollback();
                        throw;
                    }
                }
                return doc;
    }

    所谓routine代码,就是代码可以由模板生成的,就好比上下班打卡一样,是很平常的简单的行为。

    注意这里的throw代码,它没有写成这样

    catch(Exception ex)
    {
       adapter.Rollback();
       throw ex;
    }

    在《.NET框架程序设计》一书中,解释了这两个throw的区别,它们会产生不同的stack trace,异常的起始点不同。

    基础层面的问题解决了,下面的应用程序就水到渠成,以不同的方式导入文档到数据库中。

    Batch Import 批次导入指定目录的文件到数据库中

    image

    Doc Scanner 批次导入指定格式的文件到数据库中

    image

    PDF Watcher 专用于PDF文件格式的转换,导入,因为是Watcher,所以你肯定会想到是个FileSystemWatcher

    image

    Doc Loader 适用于单个文档的转换,导入,一次只处理一个文档

    image

    再来看数据库中的文档的展示,Document Explorer会展现导入进数据库的原始文件,在这里可以进行预览,删除,分类。分类之后,这个文档就好比打上了合格的标签一样,可以在以后的程序中进一步使用。否则,不分类的文件都会只停留在这里,后继的步骤无法处理。这是个文档流程上的的Policy,如果不喜欢这个步骤,可以去掉。

    image

    Document Browser 分类查看文档

    image

    左边是树型结构,右边是从属于这个分类的文档。如果要对扫描进数据库中的文件进行分类,可以这样操作

    在Document Explorer中选中一个或多个文件,点击右键Category Document

    image

    在Document Browser的左边的树中,右键Paste Document

    image

    之后就看到了效果,在.NET结点下面,展示了所Paste的文档及其属性

    image

    Document Browser左边的树是文档的分类,可对它对进新增子节点,新增加一个分类的效果如下图

    image

    Category是取自数据库中的类别表,它的脚本定义如下

    CREATE TABLE [dbo].[CATEGORY](
        [RECNUM] [int] IDENTITY(1,1) NOT NULL,
        [NAME] [nvarchar](200) NULL,
     CONSTRAINT [PK_CATEGORY] PRIMARY KEY CLUSTERED 
    (
        [RECNUM] ASC
    )WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
    ) ON [PRIMARY]

    这颗文档分类树,它的结构定义是放到本地的XML文件中,上图中所看到的树的格式定义如下

    image

    如上图所示,tag就是从数据库中获取的分类定义,依据这个标识,以检索分类的文档。在Document Browser窗体的打开与关闭时,它会持久化树的结构定义,代码如下

    protected override void OnClosed(EventArgs e)
    {
           base.OnClosed(e);
           TreeViewSerializer serializer = new TreeViewSerializer();
           serializer.SerializeTreeView(this.treeView, treeFile);
    }
    
    protected override void OnLoad(EventArgs e)
    {
            treeView.ImageList = this.imageList;
            TreeNode root=treeView.Nodes[0];
            if (File.Exists(treeFile))
            {
                    treeView.Nodes.Clear();
                    TreeViewSerializer serializer = new TreeViewSerializer();
                    serializer.DeserializeTreeView(this.treeView, treeFile);
                    treeView.ExpandAll(); 
              }
    }

    如果你对如何把树节点定义保存到文件系统中感兴趣,可以用关键字TreeViewSerializer在CodeProject中查找,这里的代码就是取自其中一篇文章的代码。

    还有另一个地方,会用到树型结构分类,在Editor编辑器的打开文件对话框中,如下图所示

    image

    这里的效果,与Document Browser的效果是完全一样的。原来以为是可以用Custom Open File Dialog来解决Open File对话框的Place Bar的问题,也就是上图中看到的左边的树的分类,也是如下图中红色边框包围的地方

    image

    要达到重写红色区域,Windows有规定的路径,并且会验证这个路径,这个办法没有通过,无奈之下才用的自定义对话框。之前见到过的软件,SharePoint Designer重写过这个Place Bar区域,可惜没有领悟它的实现原理。

    写到这里,还没有完成,这里还需要一点OFFICE 二次开发的知识,在OFFICE软件中,写入一个插件,可以把正在浏览的文档,直接导入到我的文档数据库中,如下图所示

    image

    这里已经安装了两个插件,Nitro PDF Professional和Acrobat,用于把当前DOC/DOCX文档转换为PDF文件。所以,还需要写一个把当前的DOC/DOCX文档转存到文档数据库中的插件。

    在把PDF转化为可以编辑的RTF格式过程中,遇到了不少的麻烦。把DOC/DOCX转换成PDF,这个行为,有很多开源代码可以借用,但是,倒过来,把PDF转换成DOC/DOCX,这个组件却不好找。有一种方案是把PDF转化为TIFF,然后再用OCR软件系统(ABBYY FineReader 9)来转成DOC/DOCX文件。我们做程序员的穷,没有那么多银子买昂贵的SDK License,转向寻找Crack或是Patch之类的,也没有结果。这些业界领先的技术,连Trial版本都不会出现在网上,根本没有机会Trial一把,或是把它放到虚拟机里面,永远以Trial的方式来使用。有的组件,比如PDF Focus.NET,可以试用一把,可是转换出来的文件,要么加上了Trial的水印,要么只能转换前三页,后面的都不能转换。或者有的是ActiveX版本的控件,OCX方式注册到系统中,总有这样那样的问题。杯具,想想以后要离开对Microsoft .NET Framework的依赖,离开对SQL Server的依赖,以这次的经验来看,这日子是没法过了。尽管我已经解决了这里的所有问题,仍然不愿意面对,在非数据库开发的领域,技术和知识是很值钱的。因为我们已经习惯了在数据库领域的开发,技术和知识是一文不值的,只有做出的产品才值钱,悲剧。

  • 相关阅读:
    获取某个文件夹下面的子文件夹(要求是第一级)
    操作手册
    GWT与GXT
    eclipse中出现:The project cannot be built until build path errors are resolved
    eclipse部署项目要做的工作及配置
    如何测试tomcat安装成功
    tomcat的安装及eclipse配置
    配置jdk
    oracle数据库的安装、完全卸载与plsql的安装以及与oracle的连接
    UVA
  • 原文地址:https://www.cnblogs.com/JamesLi2015/p/2223418.html
Copyright © 2011-2022 走看看