2011-04-15 34 views
2

我有一個包含指定模式文本{pattern}的word文件,我想用從數據庫中讀取的新字符串替換那些模式。所以我用我的docx模板文件打開xml讀取流,替換我的模式字符串,然後返回到流,支持下載文件而不創建臨時文件。但是當我打開它時,我生成了docx文件上的錯誤。下面是我的示例代碼打開xml替換word文件中的文本並使用MVC返回內存流

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!"); 

//Instead using this code below to write text back the original file. I write new string back to memory stream and return to a stream download file 
     //using (StreamWriter sw = new //StreamWriter(wordDoc.MainDocumentPart.GetStream(FileMode.Create))) 
     //{ 
     // sw.Write(docText); 
     //} 

     using (StreamWriter sw = new StreamWriter(mem)) 
        { 
         sw.Write(docText); 
        } 
    } 
    mem.Seek(0, SeekOrigin.Begin); 

    return File(mem, "application/octet-stream","download.docx"); //Return to download file 
} 

請給我建議任何解決方案,而不是閱讀的Word文件的文本,並替換那些預期的模式文本,然後將數據寫回原來的文件。有沒有解決方案用WordprocessingDocument庫替換文本?我怎樣才能以驗證docx文件格式返回到內存流?

回答

2

您採取的方法不正確。偶然地,如果您正在搜索的模式與某些Open XML標記匹配,則會損壞文檔。如果您搜索的文本分成多次運行,則搜索/替換代碼將無法找到文本,並且無法正常運行。如果你要搜索和WordprocessingML文檔中替換文本,有一個相當簡單的算法,您可以使用:

  • 打破所有運行到一個單一的 字符的運行。這包括 具有特殊字符的運行,如 換行符,回車或硬 選項卡。
  • 在搜索字符串中找到與 字符相匹配的 運行組很容易。
  • 一旦你已經確定了一套運行的那場比賽, 那麼你可以替換一套與新創建的運行運行 的(其中有 包含的第一個字符運行 的運行性質 相匹配的搜索字符串)。
  • 在用新創建的運行替換單字符運行 之後,您可以使用 將相鄰運行合併爲 相同的格式。

我寫了一篇博客文章,並記錄了一個屏幕演示,演示了這個算法。

博客文章:http://openxmldeveloper.org/archive/2011/05/12/148357.aspx
屏幕投射:http://www.youtube.com/watch?v=w128hJUu3GM

-Eric

1

直接寫入word文檔流確實會損壞它。 您應該寫入MainDocumentPart流,但應先截斷它。 它看起來像MainDocumentPart.FeedData(Stream sourceStream)方法將做到這一點。

我還沒有測試過,但這應該工作。

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 
} 
0
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"); 
相關問題