• .Net Core集成Office Web Apps(二)


    想要使用OWA需要一台单独的服务器来部署,这对很多人造成困难。而写该文的目的是为了分享有个OWA的集成步骤,它不仅适用于.Net开发环境,其它语言也是一样的,只要实现了需要的服务接口。并且该文不局限与OWA的研究,还包括ConfigXMLCacheRedis等技术。更重要的是熟悉.Net Core开发。

    OwaFileInfoSupportsUpdateUserCanWriteSupportsLocks属性为true时将允许用户在线编辑文件。

    在原有的基础上编辑一个test.xlsx文件,其访问链接为(测试链接没有实际意义):http://owa.test.com/x/_layouts/xlviewerinternal.aspx?edit=1&WOPISrc=http%3a%2f%2f192.168.1.1%2fapi%2fwopi%2ffiles%2ftest.xlsx&access_token=H7lFBYT4pVMK

    将弹出如下对话框

    点击编辑副本

     

    查看请求日志发现,另存副本请求将调用PutRelativeFile服务,所有我们应该再原来的基础上添加PutRelativeFile服务。

    PutRelativeFile服务

    PutRelativeFile操作将在主机上创建一个基于当前文件的副本文件,创建成功后必须将副本文件名及URL以Json的格式返回给OWA服务器。

    如果OWA客户端设置了CheckFileInfo的SupportsUpdate为true的话,就必须要实现PutRelativeFile服务,否则需要设置UserCanNotWriteRelative为true并且返回501状态码。

    Method:POST

    URI:HTTP://server/<...>/wopi*/files/<id>

    Request Headers:

    X-WOPI-Override 固定值 PUT_RELATIVE

    X-WOPI-SuggestedTarget 文件扩展名或全名(可修改)

    X-WOPI-RelativeTarget 文件全名(不可更改)

    X-WOPI-OverwriteRelativeTarget 是否覆盖文件名

    X-WOPI-Size 文件的大小bytes

    X-WOPI-FileConversion 指示请求是否转换文件

    Response Headers:

    X-WOPI-ValidRelativeTarget

    X-WOPI-Lock

    X-WOPI-LockFailureReason

    该接口需要返回的Json格式如下:

    {Name:”test.xlsx”,Url:” http://server/<...>/wopi/files/ test.xlsx”, HostViewUrl :””, HostEditUrl :””}

    说明:Name为新的文件名(如果修改的话),Url为新的文件的CheckFileInfo服务路径。

    在线Excel用到这个服务的情况有两种:

    1.另存为,如果没有实现PutRelativeFile服务,则另存为将不能使用;

    2.当编辑服务器不支持的Excel某些格式的文件时,会先保存一个系统支持格式的副本,如果没有实现PutRelativeFile服务,则不能编辑该Excel(因为保存新文件会失败);

    PutRelativeFile服务与CheckFileInfo服务的URL是相同的,只是Method不同,所以我们只需在CheckFileInfo的基础上修改。

            [RouteAttribute("files/{name}")]
            public JsonResult GetFileInfo(string name, string access_token)
            {
                string wopiType = Request.Headers["X-WOPI-Override"];
                Console.WriteLine("1.X-WOPI-Override:" + wopiType);
                if (wopiType == "PUT_RELATIVE")
                {
                    using (FileStream fs = System.IO.File.Create("Files/new_" + name))
                    {
                        Request.Body.CopyTo(fs);
                    }
                    Response.Headers.Add("X-WOPI-ValidRelativeTarget", "new_" + name);
                    Response.Headers.Add("X-WOPI-Lock", Request.Headers["X-WOPI-Lock"]);
                    Response.StatusCode = 200;
                    PutRelativeFile file = new PutRelativeFile();
                    file.Name = "new_" + name;
                    file.Url = "http://b1wcfoqm7r.proxy.qqbrowser.cc/api/wopi/files/new_" + name;
                    return Json(file);
                }
                else if (wopiType == "UNLOCK" || wopiType == "LOCK")
                {
                    Response.Headers.Add("X-WOPI-Lock", Request.Headers["X-WOPI-Lock"]);
                    Response.StatusCode = 200;
                    return Json("");
                }
                else
                {
                    FileHelper helper = new FileHelper();
                    var info = helper.GetFileInfo(name);
                    info.SupportsUpdate = true;
                    info.SupportsLocks = true;
                    info.UserCanWrite = true;
                    return Json(info);
                }
    GetFileInfo
        [DataContract(Name = "PutRelativeFile")]
        public class PutRelativeFile
        {
            [DataMember(Name = "Name")]
            public string Name { get; set; }
            [DataMember(Name = "Url")]
            public string Url { get; set; }
            [DataMember(Name = "HostViewUrl")]
            public string HostViewUrl { get; set; }
            [DataMember(Name = "HostEditUrl")]
            public string HostEditUrl { get; set; }
        }
    PutRelativeFile

    Discovery.xml

    访问OWA服务器的如下地址:http://owa.host.com/hosting/discovery(该链接无实际意义)就能得到OWA服务器能够处理的所有文件格式、操作及相关的URL。

    <action name="view" ext="xls" default="true" urlsrc="http://owa.hand-china.com/x/_layouts/xlviewerinternal.aspx?<ui=UI_LLCC&><rs=DC_LLCC&>"/>

    name=”view”表示动作为查看,ext=”xls”表示文件扩展名为xls,urlsrc则表示相应动作的地址。

    以预览test.xls为例,其ChecFileInfo路径为:http://localhost:5000/api/wopi/files/test.xls

    则最终预览的链接为:http://owa.host.com/x/_layouts/xlviewerinternal.aspx?WOPISrc=http://localhost:5000/api/wopi/files/test.xls

    我将OWA服务提交的discovery内容放到了本地的xml文件中,读取方法如下:

            public static List<DiscoveryAction> GetDiscoveryAction()
            {
                List<DiscoveryAction> list = new List<DiscoveryAction>();
                XmlReader reader = XmlReader.Create("Files/Discovery.xml");
                //循环Read方法直到文档结束  
                while (reader.Read())
                {
                    //Console.WriteLine("rdr.NodeType = " + reader.NodeType);
                    //如果是开始节点  
                    if (reader.NodeType == XmlNodeType.Element)
                    {
                        //通过rdr.Name得到节点名  
                        string elementName = reader.Name;
    
                        //读取到cat元素 这时rdr.Read()读取到的内容为<cat color="white">  
                        if (elementName == "action")
                        {
                            DiscoveryAction act = new DiscoveryAction();
                            //可以通过中括号获得属性值  
                            act.Name = reader["name"];
                            act.UrlSrc = reader["urlsrc"];
                            act.Default = TransBool(reader["default"]);
                            act.Ext = reader["ext"];
                            act.ProGid = reader["progid"];
                            act.Requires = reader["requires"];
                            list.Add(act);
                        }
                    }
                }
                return list;
            }
    GetDiscovery

    Discovery.xml文件下载:Disconvery

    Controller Action代码如下:

            [Route("files/{name}/links")]
            [HttpGetAttribute]
            public JsonResult GetOwaLinks(string name, string type, string access_token, string lang)
            {
                if (string.IsNullOrEmpty(type))
                {
                    type = "view";
                }
                if (string.IsNullOrEmpty(lang))
                {
                    lang = "zh-CN";
                }
                if (string.IsNullOrEmpty(access_token))
                {
                    access_token = "H7lFBYT4pVMK";
                }
                List<string> lst = new List<string>();
                var res = XmlHelper.GetDiscoveryAction();
                var ext = Path.GetExtension(name).TrimStart('.');
                var discovery = res.Where(t => t.Ext == ext && t.Name == type);
                foreach (var item in discovery)
                {
                    Console.WriteLine(item.UrlSrc);
                    var index = item.UrlSrc.IndexOf('<');
                    var api = System.Net.WebUtility.UrlEncode("http://localhost:5000/api/wopi/files/" + name);
                    lst.Add(string.Format(item.UrlSrc.Substring(0, index) + "WOPISrc={0}&access_token={1}&ui={2}", api, access_token, lang));
                }
                return Json(lst);
            }
    GetOwaLinks

    测试访问:http://localhost:5000/api/wopi/files/test.docx/links

  • 相关阅读:
    软件架构自学笔记-- 转载“腾讯数据库专家雷海林分享智能运维架构”
    软件架构自学笔记-- 架构设计与安全控制
    软件架构自学笔记——什么样的架构才是好的架构
    软件架构自学笔记----分享“去哪儿 Hadoop 集群 Federation 数据拷贝优化”
    软件架构自学笔记---架构分析
    软件架构自学笔记——非功能特性
    软件架构自学笔记——常见的软件架构(https://jiajunhuang.com/articles/2018_09_16-common_software_archtecture_pattern.md.html)
    微服务化的基石——持续集成
    微软开源大规模数据处理项目 Data Accelerator
    vs2019 cdkey 秘钥
  • 原文地址:https://www.cnblogs.com/liuxiaobo93/p/5834059.html
Copyright © 2020-2023  润新知