How can I form a Word document using stream of bytes












4














I have a stream of bytes which actually (if put right) will form a valid Word file, I need to convert this stream into a Word file without writing it to disk, I take the original stream from SQL Server database table:



ID   Name    FileData
----------------------------------------
1 Word1 292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)


the FileData field carries the data.



Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
doc = word.Documents.Open(@"C:SampleText.doc");
doc.Activate();


The above code opens and fill a Word file from File System, I don't want that, I want to define a new Microsoft.Office.Interop.Word.Document, but I want to fill its content manually from byte stream.



After getting the in-memory Word document, I want to do some parsing of keywords.



Any ideas?










share|improve this question



























    4














    I have a stream of bytes which actually (if put right) will form a valid Word file, I need to convert this stream into a Word file without writing it to disk, I take the original stream from SQL Server database table:



    ID   Name    FileData
    ----------------------------------------
    1 Word1 292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)


    the FileData field carries the data.



    Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
    Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
    doc = word.Documents.Open(@"C:SampleText.doc");
    doc.Activate();


    The above code opens and fill a Word file from File System, I don't want that, I want to define a new Microsoft.Office.Interop.Word.Document, but I want to fill its content manually from byte stream.



    After getting the in-memory Word document, I want to do some parsing of keywords.



    Any ideas?










    share|improve this question

























      4












      4








      4







      I have a stream of bytes which actually (if put right) will form a valid Word file, I need to convert this stream into a Word file without writing it to disk, I take the original stream from SQL Server database table:



      ID   Name    FileData
      ----------------------------------------
      1 Word1 292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)


      the FileData field carries the data.



      Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
      Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
      doc = word.Documents.Open(@"C:SampleText.doc");
      doc.Activate();


      The above code opens and fill a Word file from File System, I don't want that, I want to define a new Microsoft.Office.Interop.Word.Document, but I want to fill its content manually from byte stream.



      After getting the in-memory Word document, I want to do some parsing of keywords.



      Any ideas?










      share|improve this question













      I have a stream of bytes which actually (if put right) will form a valid Word file, I need to convert this stream into a Word file without writing it to disk, I take the original stream from SQL Server database table:



      ID   Name    FileData
      ----------------------------------------
      1 Word1 292jf2jf2ofm29fj29fj29fj29f2jf29efj29fj2f9 (actual file data)


      the FileData field carries the data.



      Microsoft.Office.Interop.Word.Application word = new Microsoft.Office.Interop.Word.Application();
      Microsoft.Office.Interop.Word.Document doc = new Microsoft.Office.Interop.Word.Document();
      doc = word.Documents.Open(@"C:SampleText.doc");
      doc.Activate();


      The above code opens and fill a Word file from File System, I don't want that, I want to define a new Microsoft.Office.Interop.Word.Document, but I want to fill its content manually from byte stream.



      After getting the in-memory Word document, I want to do some parsing of keywords.



      Any ideas?







      c# ms-word






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Aug 14 '11 at 12:39









      Kenan DKenan D

      4,4542750




      4,4542750
























          4 Answers
          4






          active

          oldest

          votes


















          0















          1. Create an in memmory file system, there are drivers for that.

          2. Give word a path to an ftp server path (or something else) which you then use to push the data.


          One important thing to note: storing files in a database is generally not good design.






          share|improve this answer





















          • Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
            – Kenan D
            Aug 14 '11 at 12:52






          • 3




            -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
            – CesarGon
            Aug 14 '11 at 19:32










          • My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
            – nulvinge
            Aug 15 '11 at 15:21






          • 1




            CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
            – nulvinge
            Aug 15 '11 at 15:26












          • Check for example: stackoverflow.com/questions/211895/…
            – nulvinge
            Aug 15 '11 at 15:26



















          0














          You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.



          Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.






          share|improve this answer





















          • Example code or link?
            – vapcguy
            Nov 19 '18 at 19:20



















          0














          There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:




          • Use the OpenOffice SDK to manipulate the document instead of Word
            Interop

          • Write the data to the clipboard, and then from the Clipboard to Word


          I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).






          share|improve this answer































            0














            There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.



            The stream method is covered here: https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream



            But even it relies on there being a physical file in order to form the stream:



            string strDoc = @"C:UsersPublicPublic DocumentsWord13.docx";
            Stream stream = File.Open(strDoc, FileMode.Open);


            The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:



            string newDocument = @"C:temptest.docx";
            WriteFile(byteArray, newDocument);


            If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.



            You'd use this WriteFile() function:



            /// <summary>
            /// Write a byte to a new file at the location where you choose
            /// </summary>
            /// <param name="byteArray">byte that consists of file data</param>
            /// <param name="newDocument">Path to where the new document will be written</param>
            public static void WriteFile(byte byteArray, string newDocument)
            {
            using (MemoryStream stream = new MemoryStream())
            {
            stream.Write(byteArray, 0, (int)byteArray.Length);

            // Save the file with the new name
            File.WriteAllBytes(newDocument, stream.ToArray());
            }
            }


            From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:



            string docText = null;
            byte byteArray = null;
            using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
            {
            using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
            {
            docText = sr.ReadToEnd(); // <-- converts byte stream to string
            }

            // Play with the XML
            XmlDocument xml = new XmlDocument();
            xml.LoadXml(docText); // the string contains the XML of the Word document

            XmlNodeList nodes = xml.GetElementsByTagName("w:body");
            XmlNode chiefBodyNode = nodes[0];
            // add paragraphs with AppendChild...
            // remove a node by getting a ChildNode and removing it, like this...
            XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
            chiefBodyNode.RemoveChild(firstParagraph);

            // Or play with the string form
            docText = docText.Replace("John","Joe");

            // If you manipulated the XML, write it back to the string
            //docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line

            // Save the file - yes, back to the file system - required
            using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
            {
            sw.Write(docText);
            }
            }

            // Read it back in as bytes
            byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


            Reference:



            https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part



            I know it's not ideal, but I have searched and not found a way to edit the byte directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.



            Update:



            It might be possible to manipulate the bytes like this:



            //byte byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
            byte byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
            using (MemoryStream mem = new MemoryStream())
            {
            mem.Write(byteArray, 0, (int)byteArray.Length);
            using (WordprocessingDocument wordDoc =
            WordprocessingDocument.Open(mem, true))
            {
            // do your updates -- see string or XML edits, above

            // Once done, you may need to save the changes....
            //wordDoc.MainDocumentPart.Document.Save();
            }

            // But you will still need to save it to the file system here....
            // You would update "documentPath" to a new name first...
            string documentPath = @"C:tempnewDoc.docx";
            using (FileStream fileStream = new FileStream(documentPath,
            System.IO.FileMode.CreateNew))
            {
            mem.WriteTo(fileStream);
            }
            }

            // And then read the bytes back in, to save it to the database
            byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


            Reference:



            https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)



            But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.



            Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:



            // Convert
            byteArray = mem.ToArray();


            This will have your Word document byte.






            share|improve this answer























              Your Answer






              StackExchange.ifUsing("editor", function () {
              StackExchange.using("externalEditor", function () {
              StackExchange.using("snippets", function () {
              StackExchange.snippets.init();
              });
              });
              }, "code-snippets");

              StackExchange.ready(function() {
              var channelOptions = {
              tags: "".split(" "),
              id: "1"
              };
              initTagRenderer("".split(" "), "".split(" "), channelOptions);

              StackExchange.using("externalEditor", function() {
              // Have to fire editor after snippets, if snippets enabled
              if (StackExchange.settings.snippets.snippetsEnabled) {
              StackExchange.using("snippets", function() {
              createEditor();
              });
              }
              else {
              createEditor();
              }
              });

              function createEditor() {
              StackExchange.prepareEditor({
              heartbeatType: 'answer',
              autoActivateHeartbeat: false,
              convertImagesToLinks: true,
              noModals: true,
              showLowRepImageUploadWarning: true,
              reputationToPostImages: 10,
              bindNavPrevention: true,
              postfix: "",
              imageUploader: {
              brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
              contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
              allowUrls: true
              },
              onDemand: true,
              discardSelector: ".discard-answer"
              ,immediatelyShowMarkdownHelp:true
              });


              }
              });














              draft saved

              draft discarded


















              StackExchange.ready(
              function () {
              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7056852%2fhow-can-i-form-a-word-document-using-stream-of-bytes%23new-answer', 'question_page');
              }
              );

              Post as a guest















              Required, but never shown

























              4 Answers
              4






              active

              oldest

              votes








              4 Answers
              4






              active

              oldest

              votes









              active

              oldest

              votes






              active

              oldest

              votes









              0















              1. Create an in memmory file system, there are drivers for that.

              2. Give word a path to an ftp server path (or something else) which you then use to push the data.


              One important thing to note: storing files in a database is generally not good design.






              share|improve this answer





















              • Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
                – Kenan D
                Aug 14 '11 at 12:52






              • 3




                -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
                – CesarGon
                Aug 14 '11 at 19:32










              • My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
                – nulvinge
                Aug 15 '11 at 15:21






              • 1




                CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
                – nulvinge
                Aug 15 '11 at 15:26












              • Check for example: stackoverflow.com/questions/211895/…
                – nulvinge
                Aug 15 '11 at 15:26
















              0















              1. Create an in memmory file system, there are drivers for that.

              2. Give word a path to an ftp server path (or something else) which you then use to push the data.


              One important thing to note: storing files in a database is generally not good design.






              share|improve this answer





















              • Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
                – Kenan D
                Aug 14 '11 at 12:52






              • 3




                -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
                – CesarGon
                Aug 14 '11 at 19:32










              • My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
                – nulvinge
                Aug 15 '11 at 15:21






              • 1




                CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
                – nulvinge
                Aug 15 '11 at 15:26












              • Check for example: stackoverflow.com/questions/211895/…
                – nulvinge
                Aug 15 '11 at 15:26














              0












              0








              0







              1. Create an in memmory file system, there are drivers for that.

              2. Give word a path to an ftp server path (or something else) which you then use to push the data.


              One important thing to note: storing files in a database is generally not good design.






              share|improve this answer













              1. Create an in memmory file system, there are drivers for that.

              2. Give word a path to an ftp server path (or something else) which you then use to push the data.


              One important thing to note: storing files in a database is generally not good design.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Aug 14 '11 at 12:48









              nulvingenulvinge

              1,407716




              1,407716












              • Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
                – Kenan D
                Aug 14 '11 at 12:52






              • 3




                -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
                – CesarGon
                Aug 14 '11 at 19:32










              • My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
                – nulvinge
                Aug 15 '11 at 15:21






              • 1




                CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
                – nulvinge
                Aug 15 '11 at 15:26












              • Check for example: stackoverflow.com/questions/211895/…
                – nulvinge
                Aug 15 '11 at 15:26


















              • Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
                – Kenan D
                Aug 14 '11 at 12:52






              • 3




                -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
                – CesarGon
                Aug 14 '11 at 19:32










              • My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
                – nulvinge
                Aug 15 '11 at 15:21






              • 1




                CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
                – nulvinge
                Aug 15 '11 at 15:26












              • Check for example: stackoverflow.com/questions/211895/…
                – nulvinge
                Aug 15 '11 at 15:26
















              Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
              – Kenan D
              Aug 14 '11 at 12:52




              Storing files in database is a must in this project, the 2nd option deals with file system so I can not accept this answer, thanks though.
              – Kenan D
              Aug 14 '11 at 12:52




              3




              3




              -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
              – CesarGon
              Aug 14 '11 at 19:32




              -1 "storing files in a database is generally not good design": why? I think this is a complex decision for which pros and cons must be considered case by case. I don't think that it is possible to state it is or it is not a good design generally. Care to explain, please?
              – CesarGon
              Aug 14 '11 at 19:32












              My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
              – nulvinge
              Aug 15 '11 at 15:21




              My second option is similar to the answer by GvS, and doesn't include the filesystem. Serve the file from memmory to a socket, which word reads. No filesystem access.
              – nulvinge
              Aug 15 '11 at 15:21




              1




              1




              CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
              – nulvinge
              Aug 15 '11 at 15:26






              CesarGon: True that you have to evaluate your options, but in the general case (the case most of us are facing) it is bad design. Databases are not designed to hold large blobs of data, and would represent that as a pointer to a blob, which one could represent as a path to a file. Working with files are simply a lot easier when the files are files. An excellent example is this question. DBs are not design for files, filesystems are.
              – nulvinge
              Aug 15 '11 at 15:26














              Check for example: stackoverflow.com/questions/211895/…
              – nulvinge
              Aug 15 '11 at 15:26




              Check for example: stackoverflow.com/questions/211895/…
              – nulvinge
              Aug 15 '11 at 15:26













              0














              You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.



              Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.






              share|improve this answer





















              • Example code or link?
                – vapcguy
                Nov 19 '18 at 19:20
















              0














              You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.



              Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.






              share|improve this answer





















              • Example code or link?
                – vapcguy
                Nov 19 '18 at 19:20














              0












              0








              0






              You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.



              Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.






              share|improve this answer












              You could look at how Sharepoint solves this. They have created a web interface for documents stored in their database.



              Its not that hard to create or embed a webserver in your application that can serve pages to Word. You don't even have to use the standard ports.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Aug 14 '11 at 20:51









              GvSGvS

              43.8k1486124




              43.8k1486124












              • Example code or link?
                – vapcguy
                Nov 19 '18 at 19:20


















              • Example code or link?
                – vapcguy
                Nov 19 '18 at 19:20
















              Example code or link?
              – vapcguy
              Nov 19 '18 at 19:20




              Example code or link?
              – vapcguy
              Nov 19 '18 at 19:20











              0














              There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:




              • Use the OpenOffice SDK to manipulate the document instead of Word
                Interop

              • Write the data to the clipboard, and then from the Clipboard to Word


              I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).






              share|improve this answer




























                0














                There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:




                • Use the OpenOffice SDK to manipulate the document instead of Word
                  Interop

                • Write the data to the clipboard, and then from the Clipboard to Word


                I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).






                share|improve this answer


























                  0












                  0








                  0






                  There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:




                  • Use the OpenOffice SDK to manipulate the document instead of Word
                    Interop

                  • Write the data to the clipboard, and then from the Clipboard to Word


                  I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).






                  share|improve this answer














                  There probably isn't any straight-forward way of doing this. I found a couple of solutions searching for it:




                  • Use the OpenOffice SDK to manipulate the document instead of Word
                    Interop

                  • Write the data to the clipboard, and then from the Clipboard to Word


                  I don't know if this does it for you, but apparently the API doesn't provide what you're after (unfortunately).







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited May 23 '17 at 9:59









                  Community

                  11




                  11










                  answered Aug 14 '11 at 19:23









                  Erik A. BrandstadmoenErik A. Brandstadmoen

                  8,09022847




                  8,09022847























                      0














                      There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.



                      The stream method is covered here: https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream



                      But even it relies on there being a physical file in order to form the stream:



                      string strDoc = @"C:UsersPublicPublic DocumentsWord13.docx";
                      Stream stream = File.Open(strDoc, FileMode.Open);


                      The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:



                      string newDocument = @"C:temptest.docx";
                      WriteFile(byteArray, newDocument);


                      If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.



                      You'd use this WriteFile() function:



                      /// <summary>
                      /// Write a byte to a new file at the location where you choose
                      /// </summary>
                      /// <param name="byteArray">byte that consists of file data</param>
                      /// <param name="newDocument">Path to where the new document will be written</param>
                      public static void WriteFile(byte byteArray, string newDocument)
                      {
                      using (MemoryStream stream = new MemoryStream())
                      {
                      stream.Write(byteArray, 0, (int)byteArray.Length);

                      // Save the file with the new name
                      File.WriteAllBytes(newDocument, stream.ToArray());
                      }
                      }


                      From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:



                      string docText = null;
                      byte byteArray = null;
                      using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
                      {
                      using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                      {
                      docText = sr.ReadToEnd(); // <-- converts byte stream to string
                      }

                      // Play with the XML
                      XmlDocument xml = new XmlDocument();
                      xml.LoadXml(docText); // the string contains the XML of the Word document

                      XmlNodeList nodes = xml.GetElementsByTagName("w:body");
                      XmlNode chiefBodyNode = nodes[0];
                      // add paragraphs with AppendChild...
                      // remove a node by getting a ChildNode and removing it, like this...
                      XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
                      chiefBodyNode.RemoveChild(firstParagraph);

                      // Or play with the string form
                      docText = docText.Replace("John","Joe");

                      // If you manipulated the XML, write it back to the string
                      //docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line

                      // Save the file - yes, back to the file system - required
                      using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                      {
                      sw.Write(docText);
                      }
                      }

                      // Read it back in as bytes
                      byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                      Reference:



                      https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part



                      I know it's not ideal, but I have searched and not found a way to edit the byte directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.



                      Update:



                      It might be possible to manipulate the bytes like this:



                      //byte byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
                      byte byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
                      using (MemoryStream mem = new MemoryStream())
                      {
                      mem.Write(byteArray, 0, (int)byteArray.Length);
                      using (WordprocessingDocument wordDoc =
                      WordprocessingDocument.Open(mem, true))
                      {
                      // do your updates -- see string or XML edits, above

                      // Once done, you may need to save the changes....
                      //wordDoc.MainDocumentPart.Document.Save();
                      }

                      // But you will still need to save it to the file system here....
                      // You would update "documentPath" to a new name first...
                      string documentPath = @"C:tempnewDoc.docx";
                      using (FileStream fileStream = new FileStream(documentPath,
                      System.IO.FileMode.CreateNew))
                      {
                      mem.WriteTo(fileStream);
                      }
                      }

                      // And then read the bytes back in, to save it to the database
                      byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                      Reference:



                      https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)



                      But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.



                      Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:



                      // Convert
                      byteArray = mem.ToArray();


                      This will have your Word document byte.






                      share|improve this answer




























                        0














                        There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.



                        The stream method is covered here: https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream



                        But even it relies on there being a physical file in order to form the stream:



                        string strDoc = @"C:UsersPublicPublic DocumentsWord13.docx";
                        Stream stream = File.Open(strDoc, FileMode.Open);


                        The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:



                        string newDocument = @"C:temptest.docx";
                        WriteFile(byteArray, newDocument);


                        If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.



                        You'd use this WriteFile() function:



                        /// <summary>
                        /// Write a byte to a new file at the location where you choose
                        /// </summary>
                        /// <param name="byteArray">byte that consists of file data</param>
                        /// <param name="newDocument">Path to where the new document will be written</param>
                        public static void WriteFile(byte byteArray, string newDocument)
                        {
                        using (MemoryStream stream = new MemoryStream())
                        {
                        stream.Write(byteArray, 0, (int)byteArray.Length);

                        // Save the file with the new name
                        File.WriteAllBytes(newDocument, stream.ToArray());
                        }
                        }


                        From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:



                        string docText = null;
                        byte byteArray = null;
                        using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
                        {
                        using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                        {
                        docText = sr.ReadToEnd(); // <-- converts byte stream to string
                        }

                        // Play with the XML
                        XmlDocument xml = new XmlDocument();
                        xml.LoadXml(docText); // the string contains the XML of the Word document

                        XmlNodeList nodes = xml.GetElementsByTagName("w:body");
                        XmlNode chiefBodyNode = nodes[0];
                        // add paragraphs with AppendChild...
                        // remove a node by getting a ChildNode and removing it, like this...
                        XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
                        chiefBodyNode.RemoveChild(firstParagraph);

                        // Or play with the string form
                        docText = docText.Replace("John","Joe");

                        // If you manipulated the XML, write it back to the string
                        //docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line

                        // Save the file - yes, back to the file system - required
                        using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                        {
                        sw.Write(docText);
                        }
                        }

                        // Read it back in as bytes
                        byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                        Reference:



                        https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part



                        I know it's not ideal, but I have searched and not found a way to edit the byte directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.



                        Update:



                        It might be possible to manipulate the bytes like this:



                        //byte byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
                        byte byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
                        using (MemoryStream mem = new MemoryStream())
                        {
                        mem.Write(byteArray, 0, (int)byteArray.Length);
                        using (WordprocessingDocument wordDoc =
                        WordprocessingDocument.Open(mem, true))
                        {
                        // do your updates -- see string or XML edits, above

                        // Once done, you may need to save the changes....
                        //wordDoc.MainDocumentPart.Document.Save();
                        }

                        // But you will still need to save it to the file system here....
                        // You would update "documentPath" to a new name first...
                        string documentPath = @"C:tempnewDoc.docx";
                        using (FileStream fileStream = new FileStream(documentPath,
                        System.IO.FileMode.CreateNew))
                        {
                        mem.WriteTo(fileStream);
                        }
                        }

                        // And then read the bytes back in, to save it to the database
                        byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                        Reference:



                        https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)



                        But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.



                        Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:



                        // Convert
                        byteArray = mem.ToArray();


                        This will have your Word document byte.






                        share|improve this answer


























                          0












                          0








                          0






                          There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.



                          The stream method is covered here: https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream



                          But even it relies on there being a physical file in order to form the stream:



                          string strDoc = @"C:UsersPublicPublic DocumentsWord13.docx";
                          Stream stream = File.Open(strDoc, FileMode.Open);


                          The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:



                          string newDocument = @"C:temptest.docx";
                          WriteFile(byteArray, newDocument);


                          If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.



                          You'd use this WriteFile() function:



                          /// <summary>
                          /// Write a byte to a new file at the location where you choose
                          /// </summary>
                          /// <param name="byteArray">byte that consists of file data</param>
                          /// <param name="newDocument">Path to where the new document will be written</param>
                          public static void WriteFile(byte byteArray, string newDocument)
                          {
                          using (MemoryStream stream = new MemoryStream())
                          {
                          stream.Write(byteArray, 0, (int)byteArray.Length);

                          // Save the file with the new name
                          File.WriteAllBytes(newDocument, stream.ToArray());
                          }
                          }


                          From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:



                          string docText = null;
                          byte byteArray = null;
                          using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
                          {
                          using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                          {
                          docText = sr.ReadToEnd(); // <-- converts byte stream to string
                          }

                          // Play with the XML
                          XmlDocument xml = new XmlDocument();
                          xml.LoadXml(docText); // the string contains the XML of the Word document

                          XmlNodeList nodes = xml.GetElementsByTagName("w:body");
                          XmlNode chiefBodyNode = nodes[0];
                          // add paragraphs with AppendChild...
                          // remove a node by getting a ChildNode and removing it, like this...
                          XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
                          chiefBodyNode.RemoveChild(firstParagraph);

                          // Or play with the string form
                          docText = docText.Replace("John","Joe");

                          // If you manipulated the XML, write it back to the string
                          //docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line

                          // Save the file - yes, back to the file system - required
                          using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                          {
                          sw.Write(docText);
                          }
                          }

                          // Read it back in as bytes
                          byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                          Reference:



                          https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part



                          I know it's not ideal, but I have searched and not found a way to edit the byte directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.



                          Update:



                          It might be possible to manipulate the bytes like this:



                          //byte byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
                          byte byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
                          using (MemoryStream mem = new MemoryStream())
                          {
                          mem.Write(byteArray, 0, (int)byteArray.Length);
                          using (WordprocessingDocument wordDoc =
                          WordprocessingDocument.Open(mem, true))
                          {
                          // do your updates -- see string or XML edits, above

                          // Once done, you may need to save the changes....
                          //wordDoc.MainDocumentPart.Document.Save();
                          }

                          // But you will still need to save it to the file system here....
                          // You would update "documentPath" to a new name first...
                          string documentPath = @"C:tempnewDoc.docx";
                          using (FileStream fileStream = new FileStream(documentPath,
                          System.IO.FileMode.CreateNew))
                          {
                          mem.WriteTo(fileStream);
                          }
                          }

                          // And then read the bytes back in, to save it to the database
                          byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                          Reference:



                          https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)



                          But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.



                          Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:



                          // Convert
                          byteArray = mem.ToArray();


                          This will have your Word document byte.






                          share|improve this answer














                          There are really only 2 ways to open a Word document programmatically - as a physical file or as a stream. There's a "package", but that's not really applicable.



                          The stream method is covered here: https://docs.microsoft.com/en-us/office/open-xml/how-to-open-a-word-processing-document-from-a-stream



                          But even it relies on there being a physical file in order to form the stream:



                          string strDoc = @"C:UsersPublicPublic DocumentsWord13.docx";
                          Stream stream = File.Open(strDoc, FileMode.Open);


                          The best solution I can offer would be to write the file out to a temp location where the service account for the application has permission to write:



                          string newDocument = @"C:temptest.docx";
                          WriteFile(byteArray, newDocument);


                          If it didn't have permissions on the "temp" folder in my example, you would simply just add the service account of your application (application pool, if it's a website) to have Full Control of the folder.



                          You'd use this WriteFile() function:



                          /// <summary>
                          /// Write a byte to a new file at the location where you choose
                          /// </summary>
                          /// <param name="byteArray">byte that consists of file data</param>
                          /// <param name="newDocument">Path to where the new document will be written</param>
                          public static void WriteFile(byte byteArray, string newDocument)
                          {
                          using (MemoryStream stream = new MemoryStream())
                          {
                          stream.Write(byteArray, 0, (int)byteArray.Length);

                          // Save the file with the new name
                          File.WriteAllBytes(newDocument, stream.ToArray());
                          }
                          }


                          From there, you can open it with OpenXML and edit the file. There's no way to open a Word document in byte form directly into an instance of Word - Interop, OpenXML, or otherwise - because you need a documentPath, or the stream method mentioned earlier that relies on there being a physical file. You can edit the bytes you would get by reading the bytes into a string, and XML afterwards, or just edit the string, directly:



                          string docText = null;
                          byte byteArray = null;
                          using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(documentPath, true))
                          {
                          using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
                          {
                          docText = sr.ReadToEnd(); // <-- converts byte stream to string
                          }

                          // Play with the XML
                          XmlDocument xml = new XmlDocument();
                          xml.LoadXml(docText); // the string contains the XML of the Word document

                          XmlNodeList nodes = xml.GetElementsByTagName("w:body");
                          XmlNode chiefBodyNode = nodes[0];
                          // add paragraphs with AppendChild...
                          // remove a node by getting a ChildNode and removing it, like this...
                          XmlNode firstParagraph = chiefBodyNode.ChildNodes[2];
                          chiefBodyNode.RemoveChild(firstParagraph);

                          // Or play with the string form
                          docText = docText.Replace("John","Joe");

                          // If you manipulated the XML, write it back to the string
                          //docText = xml.OuterXml; // comment out the line above if XML edits are all you want to do, and uncomment out this line

                          // Save the file - yes, back to the file system - required
                          using (StreamWriter sw = new StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create)))
                          {
                          sw.Write(docText);
                          }
                          }

                          // Read it back in as bytes
                          byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                          Reference:



                          https://docs.microsoft.com/en-us/office/open-xml/how-to-search-and-replace-text-in-a-document-part



                          I know it's not ideal, but I have searched and not found a way to edit the byte directly without a conversion that involves writing out the file, opening it in Word for the edits, then essentially re-uploading it to recover the new bytes. Doing byte byteArray = Encoding.UTF8.GetBytes(docText); prior to re-reading the file will corrupt them, as would any other Encoding I tried (UTF7,Default,Unicode, ASCII), as I found when I tried to write them back out using my WriteFile() function, above, in that last line. When not encoded and simply collected using File.ReadAllBytes(), and then writing the bytes back out using WriteFile(), it worked fine.



                          Update:



                          It might be possible to manipulate the bytes like this:



                          //byte byteArray = File.ReadAllBytes("Test.docx"); // you might be able to assign your bytes here, instead of from a file?
                          byte byteArray = GetByteArrayFromDatabase(fileId); // function you have for getting the document from the database
                          using (MemoryStream mem = new MemoryStream())
                          {
                          mem.Write(byteArray, 0, (int)byteArray.Length);
                          using (WordprocessingDocument wordDoc =
                          WordprocessingDocument.Open(mem, true))
                          {
                          // do your updates -- see string or XML edits, above

                          // Once done, you may need to save the changes....
                          //wordDoc.MainDocumentPart.Document.Save();
                          }

                          // But you will still need to save it to the file system here....
                          // You would update "documentPath" to a new name first...
                          string documentPath = @"C:tempnewDoc.docx";
                          using (FileStream fileStream = new FileStream(documentPath,
                          System.IO.FileMode.CreateNew))
                          {
                          mem.WriteTo(fileStream);
                          }
                          }

                          // And then read the bytes back in, to save it to the database
                          byteArray = File.ReadAllBytes(documentPath); // new bytes, ready for DB saving


                          Reference:



                          https://docs.microsoft.com/en-us/previous-versions/office/office-12//ee945362(v=office.12)



                          But note that even this method will require saving the document, then reading it back in, in order to save it to bytes for the database. It will also fail if the document is in .doc format instead of .docx on that line where the document is being opened.



                          Instead of that last section for saving the file to the file system, you could just take the memory stream and save that back into bytes once you are outside of the WordprocessingDocument.Open() block, but still inside the using (MemoryStream mem = new MemoryStream() { ... } statement:



                          // Convert
                          byteArray = mem.ToArray();


                          This will have your Word document byte.







                          share|improve this answer














                          share|improve this answer



                          share|improve this answer








                          edited Nov 20 '18 at 0:05

























                          answered Nov 19 '18 at 20:24









                          vapcguyvapcguy

                          3,0702528




                          3,0702528






























                              draft saved

                              draft discarded




















































                              Thanks for contributing an answer to Stack Overflow!


                              • Please be sure to answer the question. Provide details and share your research!

                              But avoid



                              • Asking for help, clarification, or responding to other answers.

                              • Making statements based on opinion; back them up with references or personal experience.


                              To learn more, see our tips on writing great answers.




                              draft saved


                              draft discarded














                              StackExchange.ready(
                              function () {
                              StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f7056852%2fhow-can-i-form-a-word-document-using-stream-of-bytes%23new-answer', 'question_page');
                              }
                              );

                              Post as a guest















                              Required, but never shown





















































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown

































                              Required, but never shown














                              Required, but never shown












                              Required, but never shown







                              Required, but never shown







                              Popular posts from this blog

                              MongoDB - Not Authorized To Execute Command

                              How to fix TextFormField cause rebuild widget in Flutter

                              in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith