我可以使用Office Web Apps Server吗?

我想在办公室的浏览器中建立一个文件管理系统。 我找到了这个解决方案http://www.edrawsoft.com/officeviewer.php,但它使用了办公室的客户端副本。

我想使用Office Web Apps,但我的问题是……我是否需要通过SharePoint或其他Microsoft产品使用它,或者我是否可以将浏览器中的Office Web Apps用于我自己的文档系统

您可以编写自己的服务器来实现WOPI协议,这将在视图/编辑模式下支持PPTX / XSLX,仅在视图模式下支持DOCX / PDF。 WOPI服务器实现起来非常简单。

要编辑Word文档,您需要实现Cobalt或FSSHTTP / FSSHTTPB协议。

另外不要忘记许可,Office Web Apps要求所有用户都拥有有效的办公室许可。

这是一个示例.NET WOPI服务器:

称之为:

http://OFFICEWEBAPPS.HOST/p/PowerPointFrame.aspx?PowerPointView=EditView&access_token=12345&WOPISrc=URLENCODED_URL_OF_THE_WOPI_SERVER

喜欢:http: //WOPISERVER.HOST :2000 / wopi / files / 1.pptx

这将在你的c:\ temp中打开1.pptx

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Collections; using System.Runtime.Serialization; using System.Net; using System.Net.Http; using System.Threading.Tasks; using System.Web; using System.IO; using System.Runtime.Serialization.Json; namespace WopiServerTutorial { public class WopiServer { private HttpListener Listener; static void Main(string[] args) { WopiServer s = new WopiServer(); s.Start(); Console.WriteLine("A simple wopi webserver. Press a key to quit."); Console.ReadKey(); s.Stop(); } public void Start() { Listener = new HttpListener(); Listener.Prefixes.Add(@"http://+:8080/"); Listener.Start(); Listener.BeginGetContext(ProcessRequest, Listener); Console.WriteLine(@"WopiServer Started"); } public void Stop() { Listener.Stop(); } private void ProcessRequest(IAsyncResult result) { HttpListener listener = (HttpListener)result.AsyncState; HttpListenerContext context = listener.EndGetContext(result); Console.WriteLine(@"Got a " + context.Request.HttpMethod + " request for URL: " + context.Request.Url.PathAndQuery); var stringarr = context.Request.Url.AbsolutePath.Split('/'); var rootDir = @"C:\\temp\\"; if (stringarr.Length == 5 && context.Request.HttpMethod.Equals(@"GET")) { Console.WriteLine(@"Getting content for the file: " + rootDir + stringarr[3]); // get file's content var file = rootDir + stringarr[3]; var stream = new FileStream(file, FileMode.Open); var fi = new FileInfo(file); context.Response.ContentType = @"application/octet-stream"; context.Response.ContentLength64 = fi.Length; stream.CopyTo(context.Response.OutputStream); context.Response.Close(); } //else if (stringarr.Length == 5 && context.Request.HttpMethod.Equals(@"POST")) //{ // // write //} else if (stringarr.Length == 4 && context.Request.HttpMethod.Equals(@"GET")) { Console.WriteLine(@"Getting metdata for the file: " + rootDir + stringarr[3]); var fi = new FileInfo(rootDir + stringarr[3]); CheckFileInfo cfi = new CheckFileInfo(); cfi.AllowExternalMarketplace = false; cfi.BaseFileName = fi.Name; cfi.BreadcrumbBrandName = ""; cfi.BreadcrumbBrandUrl = ""; cfi.BreadcrumbDocName = ""; cfi.BreadcrumbDocUrl = ""; cfi.BreadcrumbFolderName = ""; cfi.BreadcrumbFolderUrl = ""; cfi.ClientUrl = ""; cfi.CloseButtonClosesWindow = false; cfi.CloseUrl = ""; cfi.DisableBrowserCachingOfUserContent = true; cfi.DisablePrint = true; cfi.DisableTranslation = true; cfi.DownloadUrl = ""; cfi.FileUrl = ""; cfi.FileSharingUrl = ""; cfi.HostAuthenticationId = "s-1-5-21-3430578067-4192788304-1690859819-21774"; cfi.HostEditUrl = ""; cfi.HostEmbeddedEditUrl = ""; cfi.HostEmbeddedViewUrl = ""; cfi.HostName = @"SharePoint"; cfi.HostNotes = @"HostBIEnabled"; cfi.HostRestUrl = ""; cfi.HostViewUrl = ""; cfi.IrmPolicyDescription = ""; cfi.IrmPolicyTitle = ""; cfi.OwnerId = @"4257508bfe174aa28b461536d8b6b648"; cfi.PresenceProvider = "AD"; cfi.PresenceUserId = @"S-1-5-21-3430578067-4192788304-1690859819-21774"; cfi.PrivacyUrl = ""; cfi.ProtectInClient = false; cfi.ReadOnly = false; cfi.RestrictedWebViewOnly = false; cfi.SHA256 = ""; cfi.SignoutUrl = ""; cfi.Size = fi.Length; cfi.SupportsCoauth = false; cfi.SupportsCobalt = false; cfi.SupportsFolders = false; cfi.SupportsLocks = true; cfi.SupportsScenarioLinks = false; cfi.SupportsSecureStore = false; cfi.SupportsUpdate = true; cfi.TenantId = @"33b62539-8c5e-423c-aa3e-cc2a9fd796f2"; cfi.TermsOfUseUrl = ""; cfi.TimeZone = @"+0300#0000-11-00-01T02:00:00:0000#+0000#0000-03-00-02T02:00:00:0000#-0060"; cfi.UserCanAttend = false; cfi.UserCanNotWriteRelative = false; cfi.UserCanPresent = false; cfi.UserCanWrite = true; cfi.UserFriendlyName = ""; cfi.UserId = ""; cfi.Version = @"%22%7B59CCD75F%2D0687%2D4F86%2DBBCF%2D059126640640%7D%2C1%22"; cfi.WebEditingDisabled = false; // encode json var memoryStream = new MemoryStream(); var json = new DataContractJsonSerializer(typeof(CheckFileInfo)); json.WriteObject(memoryStream, cfi); memoryStream.Flush(); memoryStream.Position = 0; StreamReader streamReader = new StreamReader(memoryStream); var jsonResponse = Encoding.UTF8.GetBytes(streamReader.ReadToEnd()); context.Response.ContentType = @"application/json"; context.Response.ContentLength64 = jsonResponse.Length; context.Response.OutputStream.Write(jsonResponse, 0, jsonResponse.Length); context.Response.Close(); } else { byte[] buffer = Encoding.UTF8.GetBytes(""); context.Response.ContentLength64 = buffer.Length; context.Response.ContentType = @"application/json"; context.Response.OutputStream.Write(buffer, 0, buffer.Length); context.Response.OutputStream.Close(); } Listener.BeginGetContext(ProcessRequest, Listener); } } [DataContract] public class CheckFileInfo { [DataMember] public bool AllowExternalMarketplace { get; set; } [DataMember] public string BaseFileName { get; set; } [DataMember] public string BreadcrumbBrandName { get; set; } [DataMember] public string BreadcrumbBrandUrl { get; set; } [DataMember] public string BreadcrumbDocName { get; set; } [DataMember] public string BreadcrumbDocUrl { get; set; } [DataMember] public string BreadcrumbFolderName { get; set; } [DataMember] public string BreadcrumbFolderUrl { get; set; } [DataMember] public string ClientUrl { get; set; } [DataMember] public bool CloseButtonClosesWindow { get; set; } [DataMember] public string CloseUrl { get; set; } [DataMember] public bool DisableBrowserCachingOfUserContent { get; set; } [DataMember] public bool DisablePrint { get; set; } [DataMember] public bool DisableTranslation { get; set; } [DataMember] public string DownloadUrl { get; set; } [DataMember] public string FileSharingUrl { get; set; } [DataMember] public string FileUrl { get; set; } [DataMember] public string HostAuthenticationId { get; set; } [DataMember] public string HostEditUrl { get; set; } [DataMember] public string HostEmbeddedEditUrl { get; set; } [DataMember] public string HostEmbeddedViewUrl { get; set; } [DataMember] public string HostName { get; set; } [DataMember] public string HostNotes { get; set; } [DataMember] public string HostRestUrl { get; set; } [DataMember] public string HostViewUrl { get; set; } [DataMember] public string IrmPolicyDescription { get; set; } [DataMember] public string IrmPolicyTitle { get; set; } [DataMember] public string OwnerId { get; set; } [DataMember] public string PresenceProvider { get; set; } [DataMember] public string PresenceUserId { get; set; } [DataMember] public string PrivacyUrl { get; set; } [DataMember] public bool ProtectInClient { get; set; } [DataMember] public bool ReadOnly { get; set; } [DataMember] public bool RestrictedWebViewOnly { get; set; } [DataMember] public string SHA256 { get; set; } [DataMember] public string SignoutUrl { get; set; } [DataMember] public long Size { get; set; } [DataMember] public bool SupportsCoauth { get; set; } [DataMember] public bool SupportsCobalt { get; set; } [DataMember] public bool SupportsFolders { get; set; } [DataMember] public bool SupportsLocks { get; set; } [DataMember] public bool SupportsScenarioLinks { get; set; } [DataMember] public bool SupportsSecureStore { get; set; } [DataMember] public bool SupportsUpdate { get; set; } [DataMember] public string TenantId { get; set; } [DataMember] public string TermsOfUseUrl { get; set; } [DataMember] public string TimeZone { get; set; } [DataMember] public bool UserCanAttend { get; set; } [DataMember] public bool UserCanNotWriteRelative { get; set; } [DataMember] public bool UserCanPresent { get; set; } [DataMember] public bool UserCanWrite { get; set; } [DataMember] public string UserFriendlyName { get; set; } [DataMember] public string UserId { get; set; } [DataMember] public string Version { get; set; } [DataMember] public bool WebEditingDisabled { get; set; } } } 

2014年6月13日更新:

使用Cobalt API可以编辑word文档,尽管我的实现远非完美。 让我们来了解基础知识。 FSSHTTP需要在数据库中实现的Shredded Storage,SharePoint,但在查看Cobalt Assembly之后,我确定了在文件系统上创建碎片文件的方法……以下是相关代码的片段,第一部分从c获取word doc :\ tmp \ test.docx并转换为c:\ tmp \ filestore和c:\ tmp \ wacupdate中的碎片blob

  DisposalEscrow disposal = new DisposalEscrow("temp1"); CobaltFilePartitionConfig content = new CobaltFilePartitionConfig(); content.IsNewFile = false; content.HostBlobStore = new FileSystemHostBlobStore("C:\\tmp\\filestore\\", "filestore", new FileSystemHostBlobStore.Config(), disposal, true, false); content.cellSchemaIsGenericFda = true; content.CellStorageConfig = new CellStorageConfig(); content.Schema = CobaltFilePartition.Schema.ShreddedCobalt; content.PartitionId = FilePartitionId.Content; CobaltFilePartitionConfig wacupdate = new CobaltFilePartitionConfig(); wacupdate.IsNewFile = false; wacupdate.HostBlobStore = new FileSystemHostBlobStore("C:\\tmp\\wacstore\\", "wacstore", new FileSystemHostBlobStore.Config(), disposal, true, false); wacupdate.cellSchemaIsGenericFda = false; wacupdate.CellStorageConfig = new CellStorageConfig(); wacupdate.Schema = CobaltFilePartition.Schema.ShreddedCobalt; wacupdate.PartitionId = FilePartitionId.WordWacUpdate; Dictionary pd = new Dictionary(); pd.Add(FilePartitionId.Content, content); pd.Add(FilePartitionId.WordWacUpdate, wacupdate); // custom locking store is my implementation of hostlockingstore CobaltFile cobaltFile = new CobaltFile(disposal, pd, new CustomHostLockingStore(), null); var src = FileAtom.FromExisting("C:\\tmp\\Test.docx", disposal); Cobalt.Metrics o1; cobaltFile.GetCobaltFilePartition(FilePartitionId.Content).SetStream(RootId.Default.Value, src, out o1); cobaltFile.GetCobaltFilePartition(FilePartitionId.Content).GetStream(RootId.Default.Value).Flush(); cobaltFile.CommitChanges(); 

现在您已经拥有了cobaltFile,您可以使用以下命令编辑我的原始wopi代码:

  } else if (context.Request.HttpMethod.Equals(@"POST") && context.Request.Headers["X-WOPI-Override"].Equals("COBALT")) { Console.WriteLine(@"Got a cobalt request for the file"); var ms = new MemoryStream(); context.Request.InputStream.CopyTo(ms); AtomFromByteArray atomRequest = new AtomFromByteArray(ms.ToArray()); RequestBatch requestBatch = new RequestBatch(); Object ctx; ProtocolVersion protocolVersion; requestBatch.DeserializeInputFromProtocol(atomRequest, out ctx, out protocolVersion); cobaltFile.CobaltEndpoint.ExecuteRequestBatch(requestBatch); cobaltFile.CommitChanges(); var response = requestBatch.SerializeOutputToProtocol(protocolVersion); context.Response.Headers.Add("X-WOPI-MachineName", "test"); context.Response.Headers.Add("X-WOPI-CorellationID", context.Request.Headers["X-WOPI-CorrelationID"]); context.Response.Headers.Add("request-id", context.Request.Headers["X-WOPI-CorrelationID"]); context.Response.ContentType = @"application/octet-stream"; context.Response.ContentLength64 = response.Length; response.CopyTo(context.Response.OutputStream); context.Response.Close(); } 

和customlockingstore即将推出。 从碎片转换回word文档我还没有完成,但我想我知道如何

最后的更新 – 完整的解决方案在这里:

https://github.com/thebitllc/WopiBasicEditor