Open xml replace text from word file and return memory stream using MVC

拜拜、爱过 提交于 2019-12-03 20:57:59

The approach you are taking is not correct. If, by chance, the pattern you are searching for matches some Open XML markup, you will corrupt the document. If the text you are searching for is split over multiple runs, your search/replace code will not find the text and will not operate correctly. If you want to search and replace text in a WordprocessingML document, there is a fairly easy algorithm that you can use:

  • Break all runs into runs of a single character. This includes runs that have special characters such as a line break, carriage return, or hard tab.
  • It is then pretty easy to find a set of runs that match the characters in your search string.
  • Once you have identified a set of runs that match, then you can replace that set of runs with a newly created run (which has the run properties of the run containing the first character that matched the search string).
  • After replacing the single-character runs with a newly created run, you can then consolidate adjacent runs with identical formatting.

I've written a blog post and recorded a screen-cast that walks through this algorithm.

Blog post: http://openxmldeveloper.org/archive/2011/05/12/148357.aspx
Screen cast: http://www.youtube.com/watch?v=w128hJUu3GM

-Eric

brandonlin
string sourcepath = HttpContext.Server.MapPath("~/File/Form/s.docx");            
string targetPath = HttpContext.Server.MapPath("~/File/ExportTempFile/" + DateTime.Now.ToOADate() + ".docx");
System.IO.File.Copy(sourcepath, targetPath, true);
using (WordprocessingDocument wordDocument = WordprocessingDocument.Open(targetPath, true))
{
    string docText = null;
    using (StreamReader sr = new StreamReader(wordDocument.MainDocumentPart.GetStream()))
    {
        docText = sr.ReadToEnd();
    }
    Regex regexText = new Regex("Hello world!");
    docText = regexText.Replace(docText, "Hi Everyone!");
    byte[] byteArray = Encoding.UTF8.GetBytes(docText); 
    MemoryStream stream = new MemoryStream(byteArray);
    wordDocument.MainDocumentPart.FeedData(stream);
}
MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(targetPath));
return File(mem, "application/octet-stream", "download.docx");

Writing directly to the word document stream will indeed corrupt it. You should instead write to the MainDocumentPart stream, but you should first truncate it. It looks like MainDocumentPart.FeedData(Stream sourceStream) method will do just that.

I haven't tested it but this should work.

public ActionResult SearchAndReplace(string FilePath)
{
    MemoryStream mem = new MemoryStream(System.IO.File.ReadAllBytes(FilePath));
    using (WordprocessingDocument wordDoc = WordprocessingDocument.Open(mem, true))
    {
        string docText = null;
        using (StreamReader sr = new StreamReader(wordDoc.MainDocumentPart.GetStream()))
        {
            docText = sr.ReadToEnd();
        }

        Regex regexText = new Regex("Hello world!");
        docText = regexText.Replace(docText, "Hi Everyone!");

        using (MemoryStream ms = new MemoryStream())
        {
            using (StreamWriter sw = new StreamWriter(ms))
            {
                sw.Write(docText);
            }
            ms.Seek(0, SeekOrigin.Begin);
            wordDoc.MainDocumentPart.FeedData(ms);
        }
    }
    mem.Seek(0, SeekOrigin.Begin); 

    return File(mem, "application/octet-stream","download.docx"); //Return to download file
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!