[转发]ASP.NET Core2集成Office Online Server(OWAS)实现办公文档的在线预览与编辑(支持word\excel\ppt\pdf等格式)
转载自:https://www.cnblogs.com/Andre/p/9549874.html
Office Online Server是微软开发的一套基于Office实现在线文档预览编辑的技术框架(支持当前主流的浏览器,且浏览器上无需安装任何插件,支持word、excel、ppt、pdf等文档格式),其客户端通过WebApi方式可集成到自已的应用中,支持Java、C#等语言。Office Online Server原名为:Office Web Apps Server(简称OWAS)。因为近期有ASP.NET Core 2.0的项目中要实现在线文档预览与编辑,就想着将Office Online Server集成到项目中来,通过网上查找,发现大部分的客户端的实现都是基于ASP.NET的,而我在实现到ASP.NET Core 2.0的过程中也遇到了不少的问题,所以就有了今天这篇文章。
安装Office Online Server
微软的东西在安装上都是很简单的,下载安装包一路”下一步“就可完成。也可参考如下说明来进行安装:https://docs.microsoft.com/zh-cn/officeonlineserver/deploy-office-online-server
完成安装后会在服务器上的IIS上自动创建两个网站,分别为:HTTP80、HTTP809。其中HTTP80站绑定80、443端口,HTTP809站绑定809、810端口。
业务关系
1、Office Online Server服务端(WOPI Server),安装在服务器上用于受理来自客户端的预览、编辑请求等。服务端很吃内存的,单机一定不能低于8G内存。
2、Office Online Server客户端(WOPI Client),这里因为集成在了自已的项目中,所以Office Online Server客户端也就是自已的项目中的子系统。
用户通过项目中的业务系统请求客户端并发起对某一文档的预览或编辑请求,客户端接受请求后再通过调用服务端的WebApi完成一系列约定通讯后,服务端在线输出文档并完成预览与编辑功能。
实现原理
可通过如下图(图片来自互联网)能清晰的看出浏览器、Office Online Server服务端、Office Online Server客户端之间的交互顺序与关系。在这过程中,Office Online Server客户端需自行生成Token及身份验证,这也是为保障Office Online Server客户端的安全手段。
实现代码
客户端编写拦截器,拦截器中主要接受来自服务端的请求,并根据服务端的请求类型做出相应动作,请求类型包含如下几种:CheckFileInfo、GetFile、Lock、GetLock、RefreshLock、Unlock、UnlockAndRelock、PutFile、PutRelativeFile、RenameFile、DeleteFile、PutUserInfo等。具体代码如下:
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
//编写一个处理WOPI请求的客户端拦截器
namespace Lezhima.Wopi.Base
{
public class ContentProvider
{
//声明请求代理
private readonly RequestDelegate _nextDelegate; public ContentProvider(RequestDelegate nextDelegate)
{
_nextDelegate = nextDelegate;
} //拉截并接受所有请求
public async Task Invoke(HttpContext context)
{
//判断是否为来自WOPI服务端的请求
if (context.Request.Path.ToString().ToLower().IndexOf("files") >= )
{
WopiRequest requestData = ParseRequest(context.Request); switch (requestData.Type)
{
//获取文件信息
case RequestType.CheckFileInfo:
await HandleCheckFileInfoRequest(context, requestData);
break; //尝试解锁并重新锁定
case RequestType.UnlockAndRelock:
HandleUnlockAndRelockRequest(context, requestData);
break; //获取文件
case RequestType.GetFile:
await HandleGetFileRequest(context, requestData);
break; //写入文件
case RequestType.PutFile:
await HandlePutFileRequest(context, requestData);
break; default:
ReturnServerError(context.Response);
break;
}
}
else
{
await _nextDelegate.Invoke(context);
}
} /// <summary>
/// 接受并处理获取文件信息的请求
/// </summary>
/// <remarks>
/// </remarks>
private async Task HandleCheckFileInfoRequest(HttpContext context, WopiRequest requestData)
{
//判断是否有合法token
if (!ValidateAccess(requestData, writeAccessRequired: false))
{
ReturnInvalidToken(context.Response);
return;
}
//获取文件
IFileStorage storage = FileStorageFactory.CreateFileStorage();
DateTime? lastModifiedTime = DateTime.Now;
try
{
CheckFileInfoResponse responseData = new CheckFileInfoResponse()
{
//获取文件名称
BaseFileName = Path.GetFileName(requestData.Id),
Size = Convert.ToInt32(size),
Version = Convert.ToDateTime((DateTime)lastModifiedTime).ToFileTimeUtc().ToString(),
SupportsLocks = true,
SupportsUpdate = true,
UserCanNotWriteRelative = true, ReadOnly = false,
UserCanWrite = true
}; var jsonString = JsonConvert.SerializeObject(responseData); ReturnSuccess(context.Response); await context.Response.WriteAsync(jsonString); }
catch (UnauthorizedAccessException ex)
{
ReturnFileUnknown(context.Response);
}
} /// <summary>
/// 接受并处理获取文件的请求
/// </summary>
/// <remarks>
/// </remarks>
private async Task HandleGetFileRequest(HttpContext context, WopiRequest requestData)
{
//判断是否有合法token
if (!ValidateAccess(requestData, writeAccessRequired: false))
{
ReturnInvalidToken(context.Response);
return;
} //获取文件
var stream = await storage.GetFile(requestData.FileId); if (null == stream)
{
ReturnFileUnknown(context.Response);
return;
} try
{
int i = ;
List<byte> bytes = new List<byte>();
do
{
byte[] buffer = new byte[];
i = stream.Read(buffer, , );
if (i > )
{
byte[] data = new byte[i];
Array.Copy(buffer, data, i);
bytes.AddRange(data);
}
}
while (i > ); ReturnSuccess(context.Response);
await context.Response.Body.WriteAsync(bytes, bytes.Count); }
catch (UnauthorizedAccessException)
{
ReturnFileUnknown(context.Response);
}
catch (FileNotFoundException ex)
{
ReturnFileUnknown(context.Response);
} } /// <summary>
/// 接受并处理写入文件的请求
/// </summary>
/// <remarks>
/// </remarks>
private async Task HandlePutFileRequest(HttpContext context, WopiRequest requestData)
{
//判断是否有合法token
if (!ValidateAccess(requestData, writeAccessRequired: true))
{
ReturnInvalidToken(context.Response);
return;
} try
{
//写入文件
int result = await storage.UploadFile(requestData.FileId, context.Request.Body);
if (result != )
{
ReturnServerError(context.Response);
return;
} ReturnSuccess(context.Response);
}
catch (UnauthorizedAccessException)
{
ReturnFileUnknown(context.Response);
}
catch (IOException ex)
{
ReturnServerError(context.Response);
}
} private static void ReturnServerError(HttpResponse response)
{
ReturnStatus(response, , "Server Error");
} }
}
拦截器有了后,再到Startup.cs文件中注入即可,具体代码如下:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
app.UseBrowserLink();
}
else
{
app.UseExceptionHandler("/Home/Error");
} app.UseStaticFiles();
app.UseAuthentication(); //注入中间件拦截器,这是将咱们写的那个Wopi客户端拦截器注入进来
app.UseMiddleware<ContentProvider>(); app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{name?}");
});
}
至止,整个基于Office Online Server技术框架在ASP.NET Core上的文档预览/编辑功能就完成了。够简单的吧!!
总结
1、Office Online Server服务端建议在服务器上独立部署,不要与其它业务系统混合部署。因为这货实在是太能吃内存了,其内部用了WebCached缓存机制是导致内存增高的一个因素。
2、Office Online Server很多资料上要求要用AD域,但我实际在集成客户端时没有涉及到这块,也就是说服务端是开放的,但客户端是通过自行颁发的Token与验证来保障安全的。
3、利用编写中间件拦截器,并在Startup.cs文件中注入中间件的方式来截获来自WOPI服务端的所有请求,并对不同的请求
[转发]ASP.NET Core2集成Office Online Server(OWAS)实现办公文档的在线预览与编辑(支持word\excel\ppt\pdf等格式)的更多相关文章
- ASP.NET Core2集成Office Online Server(OWAS)实现办公文档的在线预览与编辑(支持word\excel\ppt\pdf等格式)
Office Online Server是微软开发的一套基于Office实现在线文档预览编辑的技术框架(支持当前主流的浏览器,且浏览器上无需安装任何插件,支持word.excel.ppt.pdf等文档 ...
- Java实现office文档与pdf文档的在线预览功能
最近项目有个需求要java实现office文档与pdf文档的在线预览功能,刚刚接到的时候就觉得有点难,以自己的水平难以在三四天做完.压力略大.后面查找百度资料.以及在同事与网友的帮助下,四天多把它做完 ...
- Atitit.office word excel ppt pdf 的web在线预览方案与html转换方案 attilax 总结
Atitit.office word excel ppt pdf 的web在线预览方案与html转换方案 attilax 总结 1. office word excel pdf 的web预览要求 ...
- 怎么在线预览.doc,.docx,.ofd,.pdf,.wps,.cad文件以及Office文档的在线解析方式。
前言 Office文件在线预览是目前移动化办公的一种新趋势.Office在线预览指的是Office系列的文件在线查看而不依附域客户端的存在.在浏览器或者浏览器控件中可以预览查看Word.PDF.Exc ...
- apache poi操作office文档----java在线预览txt、word、ppt、execel,pdf代码
在页面上显示各种文档中的内容.在servlet中的逻辑 word: BufferedInputStream bis = null; URL url = null; HttpURLConnectio ...
- 基于开源方案构建统一的文件在线预览与office协同编辑平台的架构与实现历程
大家好,又见面了. 在构建业务系统的时候,经常会涉及到对附件的支持,继而又会引申出对附件在线预览.在线编辑.多人协同编辑等种种能力的诉求. 对于人力不是特别充裕.或者项目投入预期规划不是特别大的公司或 ...
- 【ASP.NET 进阶】PDF文件在线预览(类似百度文库)
工作需要完成文档的在线预览,现在完成了第一步PDF文件的预览,步骤是通过PDF转换工具pdf2swf.exe把PDF文件转换为SWF文件,然后通过FlexPaper就可以预览了.效果如下(GIF图片太 ...
- web office apps 在线预览实践
摘要 在一些项目中需要在线预览office文档,包括word,excel,ppt等.达到预览文档的目的有很多方法,可以看我之前总结,在线预览的n种方案: [Asp.net]常见word,excel,p ...
- office web apps 整合到自己项目中(wopi实现在线预览编辑)
借助office web apps实现在线预览和在线编辑 我所有的代码都是用go语言编写,你可以直接编译后使用,不用再有其他的操作. 最近项目实在太忙,这几天才有时间,这次是重头戏,要好好琢磨一下怎么 ...
随机推荐
- 190919 python水仙花数
# 打印出所有的"水仙花数",所谓"水仙花数"是指一个三位数,# 其各位数字立方和等于该数本身.例如:153是一个"水仙花数",# 因为15 ...
- mysql主从-ms
一.环境准备 1.准备两台安装有mysql的linux服务器 2.安装的mysql版本最好相同 3.配置两台服务器的主机名和IP地址,主机名:master和slave,IP地址:192.168.0.2 ...
- 解决 SSH Connection closed by foreign host 问题
Xshell 报错 : 1.有可能是IP和别人冲突,改一下IP就好了 2.也有可能是文件权限的问题.改一下: cd /etc/ssh/ chmod ssh_host_* chmod *.pub 3.也 ...
- python链式对比
参考 https://www.cnblogs.com/shanghongyun/p/10519579.html 为什么Python中“2==2>1”结果为True在Python中,你可能会发现这 ...
- Spring -13 -Spring 中常用注解总结
1.@Component 创建类对象,相当于配置<bean/> 2.@Service 与@Component 功能相同. 2.1都写在ServiceImpl 类上. 3.@Reposito ...
- P2149 [SDOI2009]Elaxia的路线[最长公共路径]
题目描述 最近,Elaxia和w**的关系特别好,他们很想整天在一起,但是大学的学习太紧张了,他们 必须合理地安排两个人在一起的时间. Elaxia和w**每天都要奔波于宿舍和实验室之间,他们 希望在 ...
- vue和react原理性知识点
Vue组件如何通信? computed和watch有什么区别? Vue是如何实现双向绑定的? Proxy与Object.defineProperty的优劣对比? 你是如何理解Vue的响应式系统的? 既 ...
- used to do 与be used to doing /n.
1.used to do:表示过去的习惯性动作,过去如此,现在不再这样了.常译作“过去常常”.(过去时+动词不定式) He used to play basketball when he was yo ...
- 浏览器中点击链接,跳转qq添加好友的实现方式
做android三年了,都不知道到底干了啥,现在好好研究应该来得及,哈哈哈,希望看到文章的人共勉,哈哈哈(新手写文章,大佬轻喷,呜呜呜~) 好了,这篇只是记录下,项目中遇到的坑(MMP测试),哈哈哈, ...
- Linux 文件系统缓存 -针对不同数据库有不同作用
文件系统缓存 filesystem cache 许多人没有意识到.文件系统缓存对于性能的影响.Linux系统默认的设置倾向于把内存尽可能的用于文件cache,所以在一台大内存机器上,往往我们可能发现没 ...