Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Office Web Apps Word Editing

The idea is to build a proprietary Java back end document system using Office Web Apps.

We have created the WOPI client which allows us to view/edit PowerPoint and Excel web app documents but we can only view Word Documents.

In order to edit Word Web App documents you need to implement MS-FSSHTTP.

It appears there is no information about how to actually do this in code. Has anyone performed this or would know how?

like image 615
topcat3 Avatar asked Jun 24 '13 16:06

topcat3


1 Answers

recently my team and I have implemented a WOPI-Host that supports viewing and editing of Word, PPT and Excel documents. You can take a look at https://github.com/marx-yu/WopiHost which is a command prompt project that listens on the 8080 port and enables editing and viewing of word documents though the Microsoft Office Web Apps.

We have implemented this solution in a webApi and it works great. Hope this sample project will help you out.

After requested, I will try and add code samples to clarify the way to implement it based on my webApi implementation, but their is a lot of code to implement to actually make it work properly.

First things first, to enabled editing you will need to capture Http Posts in a FilesController. Each posts that concern the actual editing will have the header X-WOPI-Override equal to COBALT. In these post you will find out that the InputStream is and Atom type. Based on the MS-WOPI documentation, in your response you will need to include the following headers X-WOPI-CorrelationID and request-id.

Here is the code of my webApi post method (it is not complete since I'm still implementing that WOPI protocol).

string wopiOverride = Request.Headers.GetValues("X-WOPI-Override").First();
if (wopiOverride.Equals("COBALT"))
{
   string filename = name;
   EditSession editSession = CobaltSessionManager.Instance.GetSession(filename);
   var filePath = HostingEnvironment.MapPath("~/App_Data/");
   if (editSession == null){
      var fileExt = filename.Substring(filename.LastIndexOf('.') + 1);
      if (fileExt.ToLower().Equals(@"xlsx"))
         editSession = new FileSession(filename, filePath + "/" + filename, @"yonggui.yu", @"yuyg", @"[email protected]", false);
      else
         editSession = new CobaltSession(filename, filePath + "/" + filename, @"patrick.racicot", @"Patrick Racicot", @"[email protected]", false);
         CobaltSessionManager.Instance.AddSession(editSession);
      }

      //cobalt, for docx and pptx
      var ms = new MemoryStream();

      HttpContext.Current.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);
      editSession.ExecuteRequestBatch(requestBatch);


      foreach (Request request in requestBatch.Requests)
      {
         if (request.GetType() == typeof(PutChangesRequest) && request.PartitionId == FilePartitionId.Content)
         {
             //upload file to hdfs
             editSession.Save();
         }
      }
      var responseContent = requestBatch.SerializeOutputToProtocol(protocolVersion);
      var host = Request.Headers.GetValues("Host");
      var correlationID = Request.Headers.GetValues("X-WOPI-CorrelationID").First();

      response.Headers.Add("X-WOPI-CorrelationID", correlationID);
      response.Headers.Add("request-id", correlationID);
      MemoryStream memoryStream = new MemoryStream();

      var streamContent = new PushStreamContent((outputStream, httpContext, transportContent) =>
      {
         responseContent.CopyTo(outputStream);
         outputStream.Close();
      });

      response.Content = streamContent;
      response.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
      response.Content.Headers.ContentLength = responseContent.Length;
}

As you can see in this method I make use of CobaltSessionManager and CobaltSession which are used to create and manage editing sessions on the Cobalt protocol. You will also need a what I call CobaltHostLockingStore which is used to handle the different requests when communicating with the Office Web App server in the edition initialization.

I won't be posting the code for these 3 classes since they are already coded in the sample github project I posted and that they are fairly simple to understand even though they are big.

If you have more questions or if it's not clear enough don't hesitate to comment and I will update my post accordingly.

like image 92
Patrick Racicot Avatar answered Sep 28 '22 09:09

Patrick Racicot