讲述了如何通过iis的webdav支持实现客户端的office直接编辑服务器上的文件,
本篇将讲解如何实现客户端的office直接编辑数据库中的二进制形式保存的office文件。

实现的关键:模拟IIS,自己实现一个webdav的服务器端。

首先,我们简单了解一下webdav:
webdav,中文可以翻译为网络分布式协作协议,它解决了http协议中一个问题:http无法实现版本和单访问控制。
什么是单访问控制呢?假设我们有一个页面编辑某条数据,这个页面可以同时被多个用户使用,那么最终的数据是最后一个用户提交的数据,
而其他用户是不知道的.我们的99%的web程序都存在此问题,当然通过编码可以解决,但http协议本身并没有提供对这种情形的支持。

webdav协议在标准的http协议的基础上,扩展了以下请求动作(verb):
PUT:用于客户端推送二进制文件。(好像http有这个verb)
LOCK:用户锁定一个资源,保证资源的单访问
UNLOCK:解锁一个资源
OPTIONS:获取服务器可以支持的请求类型
DELETE:删除服务器文件
PROPFIND:查询文件属性
其他动作: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH
要详细地了解webdav,大家可以google一下,或访问http://en.wikipedia.org/wiki/WebDAV

笔者在实现这个解决方案的时候,是采用fiddler,debug IE的http请求,才搞懂了IIS本身的实现机制,为了形象化,可以看一下webdav请求相应的
数据:
发起一个OPTIONS请求
OPTIONS /PMDemo/Test/待办事务.doc HTTP/1.1
User-Agent: Fiddler
Host: localhost

响应如下:
HTTP/1.1 200 OK
Date: Wed, 27 Dec 2006 11:34:03 GMT
Server: Microsoft-IIS/6.0
MicrosoftOfficeWebServer: 5.0_Pub
X-Powered-By: ASP.NET
MS-Author-Via: DAV
Content-Length: 0
Accept-Ranges: bytes
DASL: <DAV:sql>
DAV: 1, 2
Public: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH
Allow: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, COPY, MOVE, PROPFIND, PROPPATCH, SEARCH, LOCK, UNLOCK
Cache-Control: private

搞清楚了这些,下面我们的任务就是如何在asp.net中实现一个wevdav服务器.
显然,这要求我们需要在底层截获http请求,幸运的是asp.net中支持这种技术:HttpHandler.它可以让我们自己的代码来处理http请求.

首先,我们在web.config中做如下配置:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->    <httpHandlers>
            <remove verb="*" path="*"/>            
            <add verb="GET,PUT,UNLOCK,LOCK,OPTIONS" path="*.doc,*.xml" type="Webdav.WebdavProtocolHandler,Webdav"/>
     </httpHandlers>

通过这个配置,使我们的WebdavProtocolHandler可以来处理webdav请求.

WebdavProtocolHandler类是一个标准的httphandler,实现了IHttpHandler接口,它按照客户端的请求类型,返回符合wevdav协议的数据.

WebdavProtocolHandler类需要按照不同的webdav请求动作,做不同的处理,那么怎么来实现这个类呢?
这里就要用到一个设计模式:命令模式.

首先定义一个接口:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->public interface IVerbHandler
{
      void Process( HttpContext context );
}

实现对Options请求的处理:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->class OptionsHandler : IVerbHandler
    {
        #region IVerbHandler 成员

public void Process(System.Web.HttpContext context)
        {
            context.Response.AppendHeader("DASL", "<DAV:sql>");
            context.Response.AppendHeader("DAV", "1, 2");

context.Response.AppendHeader("Public", "OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH");

context.Response.AppendHeader("Allow", "OPTIONS, TRACE, GET, HEAD, DELETE, PUT, COPY, MOVE, PROPFIND, PROPPATCH, SEARCH, LOCK, UNLOCK");
        }

#endregion
    }

webdav的请求verb多达15个以上,大多数情况下,我们并不需要一个完整的webdav支持,故我们只要对其中的几个进行实现即可。

实现对LOCK的支持:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--> class LockHandler : IVerbHandler
    {
        #region IVerbHandler 成员

public void Process(System.Web.HttpContext context)
        {
            context.Response.ContentType = "text/xml";

string token = Guid.NewGuid().ToString() + ":" + DateTime.Now.Ticks.ToString() ;

context.Response.AppendHeader("Lock-Token", "<opaquelocktoken:" + token + ">");
          
            string xml = @"<?xml version=""1.0""?>
<a:prop xmlns:a=""DAV:""><a:lockdiscovery>
<a:activelock><a:locktype><a:write/></a:locktype>
<a:lockscope><a:exclusive/></a:lockscope><owner xmlns=""DAV:"">Administrator</owner><a:locktoken>
<a:href>opaquelocktoken:{0}</a:href></a:locktoken>
<a:depth>0</a:depth><a:timeout>Second-180</a:timeout></a:activelock></a:lockdiscovery>
</a:prop>";

context.Response.Write( String.Format( xml , token ) );
            context.Response.End();
        }

#endregion
    }

注意这篇文章的主题:实现在线编辑。并没有版本控制等其他内容,大家仔细看以上的代码,服务器并没有真正实现"锁定",只是假装告诉客户端,你要的资源已经给你锁定了,你可以放心的编辑了。当然,有兴趣的朋友可以实现真正的锁定,无非可以通过给数据做一个状态字段来实现。但注意,要考虑一些复杂的情况,如自动解锁(用户打开一个文档,然后关机了,文档岂不永远锁定了?)等等。

接着,我们实现UNLOCK,同样是假的:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->class UnLockHandler : IVerbHandler
    {
        #region IVerbHandler 成员

public void Process(System.Web.HttpContext context)
        {            
        }

#endregion
    }

下面,我们将实现两个最重要的请求动作的处理:Get和Put, office请求打开一个服务器上的文件时,采用get请求,office保存一个文件到服务器上时,发送put请求。

首先,我们要考虑一种数据项标识的传递策略,即:客户端发起访问数据库的office文件行,那么如何确认数据行的主键?
有两种策略:
1)通过不同的文件名 , 如,请求http://localhost/weboffice/1.doc  这个请求主键 为1的文件。
2)通过文件路径, 如,请求http://localhost/weboffice/1/文件名.doc  这个请求主键为1的文件。
我们将采用策略2。

再返回到我们对web.config做的配置:

<add verb="GET,PUT,UNLOCK,LOCK,OPTIONS" path="*.doc,*.xml" type="Webdav.WebdavProtocolHandler,Webdav"/>

这个配置允许WebdavProtocolHandler处理所有对doc和xml的请求处理,为什么要允许xml呢,因为office2003之后,支持xml格式,可以直接在
数据库重以xml的格式存放office文件。

接着,我们要确认我们的数据存储结构,即,office文件在数据库中时如何存放的。

我们有一个附件表:Document



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->) COLLATE Chinese_PRC_CI_AS NULL ,
    [TemplateAble] [bit] NULL 
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO

设计一个文裆实体:

 ];
       }   
   }

考虑到数据操作逻辑的可变性,不同的项目里面附件表设计的不同,这里引入一个数据操作接口:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->public interface IWebdavDocumentHandler
{
        Document GetDocument(int id);//获取文档数据
        void ModifyDocContent(int docId, byte[] data);//修改文档内容
}

具体的实现这里就不写了。

好了,我们的数据访问逻辑已经有了,那么首先看get动作处理的实现:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->)
                context.Response.BinaryWrite(doc.Content);

context.Response.End();
        }
        #endregion
    }

很简单吧,跟我们普通实现文档下载的代码一样。

put动作的实现:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->, doc.Size );
            doc.ContentType = request.ContentType;
            return doc;
        }
        #endregion
    }

OK,主要的动作都实现了,下面,我们需要WebdavProtocolHandler将各命令处理对象整合到一起:



Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

-->];
            return Convert.ToInt32( id );
        }
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest Request = context.Request;
            context.Response.AppendHeader("OpenWebDavServer", "1.0");
            string verb = Request.HttpMethod;
            //Log.Write(verb);
            IVerbHandler vh = GetVerbHandler( verb );

if( vh == null )
                return ;

vh.Process(context);      
        }

private IVerbHandler GetVerbHandler(string verb)
        {
            switch (verb)
            {
                case "LOCK" :
                    return new LockHandler();
                case "UNLOCK":
                    return new UnLockHandler();
                case "GET":
                    return new GetHandler();
                case "PUT":
                    return new PutHandler();               
                case "OPTIONS":
                    return new OptionsHandler();
                default :
                    return null;
            }
        }    
        public bool IsReusable
        {
            get { return false; }
        }
    }

到这里呢,已经基本上算game over了,基于以上代码设计,可以完全实现office文档的在线编辑。若要通过链接直接打开编辑,可以
采用Office文档在线编辑的实现之一的Document_Edit2函数触发office编辑。

哦,IIS还需要做一点小配置:
1)将.doc , .xml 加入到站点虚拟目录的isapi映射, 不要选中 "确认文件是否存在",动作要选全部动作,
2)禁用IIS本身的Webdav扩展,
3)删除虚拟目录HTTP头中的自定义HTTP头: MicrosoftOfficeWebServer,如果有的话。

Office文档在线编辑的实现之二的更多相关文章

  1. Office文档在线编辑的实现之一

    因为项目的关系,研究了一下Office的在线编辑功能,写出来共享一下. Office xp之后的版本支持通过webdav协议(http的扩展)直接编辑服务器上的文件. IIS(6.0)支持webdav ...

  2. 使用WebDAV实现Office文档在线编辑

    Office的文档处理能力是非常强大的,但是它是本地资源,在Office Web App尚未成熟前,仍需要使用本地能力来进行文档编辑,可是现代的系统的主流却是B/S,所以在B/S中调用本地的Offic ...

  3. wps金山文档在线编辑--.Net 接入指南

    一.申请成为服务商,对金山文档在线服务进行申请 ①进入官网 https://open.wps.cn/ ②申请后如下图,点击右下角的进入服务 ③申请成功后 ④数据回调URL一定是服务器地址,本次我使用的 ...

  4. Office文档在线预览

    工具说明:通过传入文档的Web地址,即可进行Office文档的在线预览. 使用方式: 在http://office.qingshanboke.com地址后,通过url参数传入您想预览的文件路径. 如: ...

  5. 在线预览-Java 使用 Print2Flash 实现Office文档在线阅读

    近期项目上遇到一个需求是用户上传的文档进行在线浏览,之前有过一篇使用 OpenOffice 将 word 转换成 html 页面进行展示的.现在介绍一个新的工具那就是 Print2Flash .    ...

  6. Java版office文档在线预览

    java将office文档pdf文档转换成swf文件在线预览 第一步,安装openoffice.org openoffice.org是一套sun的开源office办公套件,能在widows,linux ...

  7. 使用NextCloud搭建私有网络云盘并支持Office文档在线预览编辑以及文件同步

    转载自:https://www.bilibili.com/read/cv16835328?spm_id_from=333.999.0.0 0x00 前言简述 描述:由于个人家里的NAS以及公司团队对私 ...

  8. 快速实现office文档在线预览展示(doc,docx,xls,xlsx,ppt,pptx)

    微软:https://view.officeapps.live.com/op/view.aspx?src=(输入你的文档在服务器中的地址):

  9. OFFICE 文档转换为html在线预览

    OFFICE 文档在线预览方案很多: 服务器先转换为PDF,再转换为SWF,最后通过网页加载Flash预览,比如flexpaper Office文档直接转换为SWF,通过网页加载Flash预览 微软的 ...

随机推荐

  1. 【CTO辩论】移动创业大军:谁斗争or变更代理

    众创时代.英雄辈出. 但千军万马过独木桥,竞争厮杀也异常残酷.有人说,这个时代不宜创业,由于技术门槛高了.推广难度高了.盈利模式没了.创业变重了.玩法变了...... 也有人说,时势造英雄.天时地利人 ...

  2. react.js 从零开始(二)组件的生命周期

    什么是生命周期? 组件本质上是一个状态机,输入确定,输出一定确定. 当状态改变的时候 会触发不同的钩子函数,可以让开发者做出响应.. 一个组件的生命周期可以概括为 初始化:状态下 可以自定义的函数 g ...

  3. iBatis多表查询

    <typeAlias alias="Product" type="com.shopping.entity.Product"/> <typeAl ...

  4. unix cd使用命令

    [语法]:     cd   [夹] [说明]:此命令用于工作文件以改变当前的文件夹,使用环境变量没有参数$HOME 作为它的参数,$HOME 路径通常在注册时输入. [抽样]: cd   文件夹 c ...

  5. Spring搭建MVC WEB项目[转]

    原文链接:http://blog.csdn.net/initphp/article/details/8208349 1.创建一个web项目 2.假设,我们已经安装完毕Spring所需要的依赖包,以及一 ...

  6. crawler_浅谈网络爬虫

    题记: 1024,今天是个程序猿的节日 ,哈哈,转为正题,从事了一线网络爬虫开发有近1000天.简单阐述下个人对网络爬虫的理解. 提纲: 1:是什么 2:能做什么 3:怎么做 4:综述 1:是什么 w ...

  7. Opencv on Ubuntu (from Ubuntu)

     OpenCV Introduction Contents Introduction Installation Step 1 Step 2 Running OpenCV Python in C I ...

  8. jQuery组织您钞四----jQuery操作DOM

    一.采用jQuery创建节点 节点是DOM基础设施.依据DOM产品规格,Node是一个很宽泛的概念,包含元素.属性.正文.档..实际开发过程中,要创建动态内容,主要操作的节点包括元素. 属性和文本. ...

  9. Swift语言指南(九)--基本运算符

    原文:Swift语言指南(九)--基本运算符 运算符(operator)是用来检查,改变或合并值的一种特殊符号或短语.例如,加号运算符让两个数字相加(如:let i = 1 + 2),还有些更复杂的运 ...

  10. poj 3026 Borg Maze (bfs + 最小生成树)

    链接:poj 3026 题意:y行x列的迷宫中,#代表阻隔墙(不可走).空格代表空位(可走).S代表搜索起点(可走),A代表目的地(可走),如今要从S出发,每次可上下左右移动一格到可走的地方.求到达全 ...