【问题标题】:Can I just use Office Web Apps Server我可以只使用 Office Web Apps Server
【发布时间】:2013-06-12 12:03:34
【问题描述】:

我正在尝试在带有 Office 的浏览器中安装一个文档管理系统。我找到了这个解决方案http://www.edrawsoft.com/officeviewer.php,但它使用的是 office 的客户端副本。

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

【问题讨论】:

    标签: c# .net sharepoint ms-office ms-wopi


    【解决方案1】:

    您可以编写自己的实现 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<FilePartitionId, CobaltFilePartitionConfig> pd = new Dictionary<FilePartitionId, CobaltFilePartitionConfig>();
                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();
    

    现在你有了钴文件,你可以用这个来编辑我原来的 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 即将推出。从 shredded 转换回 word 文档我还没有做,但我想我知道怎么做

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

    https://github.com/thebitllc/WopiBasicEditor

    【讨论】:

    • 我在 Windows Server 2012 的虚拟机上安装了 Office Web Apps,可以点击 localhost/hosting/discovery 。我想知道现在如何测试这个
    • 这个指南是我所需要的我相信blogs.msdn.com/b/officedevdocs/archive/2013/03/20/…
    • 非常感谢。如果你能在这里回答stackoverflow.com/questions/16937990/…我会把赏金奖励给你。同样的答案适合我的需要
    • 如果您能提供帮助,我们有一个小问题。一切似乎都正常,但无法加载文件。我们在上面的问题中添加了错误。在浏览器中有抱歉,我们遇到了问题。请再试一次
    • @windfly2006 编辑word文档需要实现FSSHTTP协议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-14
    • 2017-07-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多