Редактирование Word в Office Web Apps

Идея состоит в том, чтобы создать собственную систему документов Java-приложений с использованием Office Web Apps.

Мы создали клиент WOPI, который позволяет нам просматривать / редактировать документы веб-приложений PowerPoint и Excel, но мы можем только просматривать документы Word.

Для редактирования документов Word Web App необходимо реализовать MS-FSSHTTP.

Похоже, что нет никакой информации о том, как на самом деле сделать это в коде. Кто-нибудь выполнил это или знает как?

2 ответа

Недавно мы с моей командой внедрили WOPI-Host, который поддерживает просмотр и редактирование документов Word, PPT и Excel. Вы можете взглянуть на https://github.com/marx-yu/WopiHost который является проектом командной строки, который прослушивает 8080 порт и позволяет редактировать и просматривать текстовые документы через Microsoft Office Web Apps.

Мы внедрили это решение в WebApi, и оно прекрасно работает. Надеюсь, этот пример проекта поможет вам.

После запроса я попытаюсь добавить примеры кода, чтобы прояснить способ его реализации на основе моей реализации webApi, но их достаточно для реализации, чтобы заставить его работать должным образом.

Перво-наперво, чтобы включить редактирование, вам нужно будет захватить сообщения Http в FilesController. Каждая публикация, которая касается фактического редактирования, будет иметь заголовок X-WOPI-Override равно COBALT, В этом посте вы узнаете, что InputStream имеет тип Atom. Исходя из документации MS-WOPI, в ваш ответ вам нужно будет включить следующие заголовки X-WOPI-CorrelationID а также request-id,

Вот код моего пост-метода webApi (он не завершен, так как я все еще реализую этот протокол WOPI).

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", @"yonggui.yu@emacle.com", false);
      else
         editSession = new CobaltSession(filename, filePath + "/" + filename, @"patrick.racicot", @"Patrick Racicot", @"patrick.racicot@hospitalis.com", 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;
}

Как вы можете видеть в этом методе, я использую CobaltSessionManager а также CobaltSession которые используются для создания и управления сеансами редактирования по протоколу Cobalt. Вам также понадобится то, что я называю CobaltHostLockingStore, которое используется для обработки различных запросов при взаимодействии с сервером Office Web App при инициализации выпуска.

Я не буду публиковать код для этих 3 классов, так как они уже написаны в примере проекта Github, который я опубликовал, и что их довольно просто понять, даже если они большие.

Если у вас есть еще вопросы или если это не совсем понятно, не стесняйтесь комментировать, и я обновлю свой пост соответственно.

Патрик Racicot, предоставил отличный ответ. Но у меня были проблемы с сохранением docx(исключение в CobaltCore.dll), и я даже начал использовать отражатель dotPeak, пытаясь выяснить это.

Но после того, как я запер editSession Переменная в моем методе WebApi все начало работать как по волшебству. Похоже, что OWA отправляет запросы, которые должны обрабатываться как цепочка, а не параллельно, как обычно действует метод контроллера.

Другие вопросы по тегам