Update MemoryStream when replacing BookMark

0

I'm doing a RESTFUL service in C # that has a byte array of a WORD document, and in that document I need to replace the existing bookmarks with text that are also passed in the method.

  • Problem : When replacing bookmarks with the appropriate text I can not update the MemoryStream to get the byte array updated with the modifications in the file. Someone has already had to work with

  • Report Reference

    public class ReferenciaRelatorio
    {
           public string referencia {get; set;}
           public object valor { get; set; }
     }
    
  • SD report

     [DataContract]
     public class RelatorioDS
     {        
         [DataMember]
         public List<ReferenciaRelatorio> mapaDeSubstituicao { get; set; }
         /**arquivo binario na base 64**/
        [DataMember]
        public string template { get; set; }
     }
    
  • GeneratorReportWord ( EDIT )

    using System;
    using System.IO;
    
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Microsoft.Office.Interop.Word;
    using DocumentFormat.OpenXml.Packaging;
    using DocumentFormat.OpenXml.Wordprocessing;
    using DocumentFormat.OpenXml;
    
    
    
    namespace RestService
    {
    public class GeradorRelatorioWord 
    {
    
       public ResponseData gerarRelatorio(RelatorioDS data)
       {
          ResponseData resposta =  new ResponseData();
          try
          {
             byte[] saida = null;
             byte[] template = System.Convert.FromBase64String(data.template);
             using (MemoryStream mem = new MemoryStream(template))
             {
                /**EDITADO**/
                /**mem.Write(template, 0, (int)template.Length);**/
               using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, false))
               {
                 var bookMarks = recuperarBookMark(wordDoc.MainDocumentPart.Document);
                 substituirBookMark(data, bookMarks);
                 byte[] buf;  
                 Stream stream = wordDoc.MainDocumentPart.GetStream();
                 buf = new byte[stream.Length];  
                 stream.Read(buf, 0, buf.Length);
                 saida = buf ;
    
    
                 /** EDITADO **/
                 /**
                 wordDoc.MainDocumentPart.Document.Save();
                 wordDoc.Close();
                 using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                 {
                   string documentoTexto = sr.ReadToEnd();
    
                   using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                   {
                     sw.Write(documentoTexto);
    
                     MemoryStream me = new MemoryStream();
                     sw.BaseStream.CopyTo(me);
                     saida = me.ToArray();
                   }
    
    
                 }**/
    
               }
               resposta.relatorio = System.Convert.ToBase64String(saida);
    
             }
        }
        catch(Exception e)
        {
    
          resposta.erros.Add(new MensagemErro(e));
    
        }
        return resposta;
       }
    
       /**
       * Recupera os BookMarks que existirem
       **/
       private Dictionary<string, BookmarkEnd> recuperarBookMark(OpenXmlElement documentPart, Dictionary<string, BookmarkEnd> results = null, Dictionary<string, string> unmatched = null)
       {
          results = results ?? new Dictionary<string, BookmarkEnd>();
          unmatched = unmatched ?? new Dictionary<string, string>();
    
          foreach (var child in documentPart.Elements())
          {
              if (child is BookmarkStart)
              {
                var bStart = child as BookmarkStart;
                unmatched.Add(bStart.Id, bStart.Name);
              }
    
              if (child is BookmarkEnd)
              {
                var bEnd = child as BookmarkEnd;
                foreach (var orphanName in unmatched)
                {
                 if (bEnd.Id == orphanName.Key)
                 results.Add(orphanName.Value, bEnd);
                }
              }
    
              recuperarBookMark(child, results, unmatched);
          }
    
          return results;
       }
    
       /**
       * substitui os bookmarks
       *
       *
       **/
       private static void substituirBookMark(RelatorioDS data, Dictionary<string, BookmarkEnd> bookMarks)
       {
          foreach (var end in bookMarks)
          {
            string bookmark = Uri.UnescapeDataString(end.Key);
            foreach (ReferenciaRelatorio entry in data.mapaDeSubstituicao)
            {
              if (bookmark.Equals(entry.referencia))
              {
                var textElement = new Text((string)entry.valor);
                var runElement = new Run(textElement);
    
                end.Value.InsertAfterSelf(runElement);
              }
    
            }
    
          }
       }
    
    
    }
    }
    
asked by anonymous 23.10.2014 / 19:44

1 answer

1

Your code that handles the stream has some problems:

First, when you type in stream mem , the stream cursor is at the end of the stream, which can cause your reading to not work. Tip: Change the code snippet

byte[] template = System.Convert.FromBase64String(data.template);
using (MemoryStream mem = new MemoryStream())
{
    mem.Write(template, 0, (int)template.Length);
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))

by

byte[] template = System.Convert.FromBase64String(data.template);
using (MemoryStream mem = new MemoryStream(template))
{
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, false))

Second: the stream of the word document is not necessarily text; using a StreamReader and converting to text (using UTF-8 or another standard encoding) will probably cause data loss. Change the passage

using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
{
    string documentoTexto = sr.ReadToEnd();
    using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
    {
        sw.Write(documentoTexto);
        MemoryStream me = new MemoryStream();
        sw.BaseStream.CopyTo(me);
        saida = me.ToArray();
    }
}

by

using (var mem = new MemoryStream()) {
    wordDoc.MainDocumentPart.GetStream().ToArray().CopyTo(mem);
    saida = mem.ToArray();
}
    
23.10.2014 / 19:58