Откройте xml замените текст из файла word и верните поток памяти с помощью MVC
У меня есть файл word, который содержит мой указанный текст шаблона {pattern}, и я хочу заменить этот шаблон новой моей строкой, которая была прочитана из базы данных. Поэтому я использовал open xml read stream из моего файла шаблона docx замените мою строку шаблона, а затем вернитесь в поток, который поддерживает загрузку файла без создания временного файла. Но когда я открыл его сгенерировал мне ошибку на файле docx. Ниже приведен мой пример кода
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 libary? Как я могу вернуться в поток памяти с проверкой формата файлов docx?
3 ответов:
Подход, который вы принимаете, не является правильным. Если случайно шаблон, который вы ищете, совпадает с некоторой разметкой Open XML, вы повредите документ. Если текст, который вы ищете, разбит на несколько запусков, ваш код поиска / замены не найдет текст и не будет работать правильно. Если вы хотите найти и заменить текст в документе WordprocessingML, существует довольно простой алгоритм, который вы можете использовать:
- разбить все прогоны на прогоны одного характер. Этот включает в себя запуски, которые имеют специальные символы, такие как разрыв строки, возврат каретки или жесткий вкладка.
- тогда довольно легко найти набор запусков, соответствующих символам в строке поиска.
- После того, как вы определили набор запусков, которые соответствуют, затем вы можете заменить этот набор запусков с недавно созданным запуском (который имеет свойства выполнения запуска содержащий первый символ, который соответствует строке поиска).
- после замены односимвольных запусков с новым созданный бег, вы можете затем закрепить соседними работает с одинаковое форматирование.
Я написал сообщение в блоге и записал сценарий, который проходит через этот алгоритм.
Блоге: http://openxmldeveloper.org/archive/2011/05/12/148357.aspx
Актерский состав экрана: http://www.youtube.com/watch?v=w128hJUu3GM- Эрик
Запись непосредственно в поток документов 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 }
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");
Comments