ASP.NET Core 6中.docx文件读取编辑乱码问题(无外部包)
问题根源
别懵,这是格式本质问题:
- .doc是老版Word的二进制格式,你直接读文本碰巧能凑合用;
- .docx根本不是纯文本文件,它是个ZIP压缩包,里面装着一堆XML格式的文档内容。你用
File.ReadAllText把压缩的二进制数据当UTF8文本读,再写回去,直接把压缩包结构搞崩了,打开当然是乱码。
无外部包解决方案
核心就是对docx做「解压→改XML→重新压缩」的操作,用.NET自带的System.IO.Compression就能搞定,不用装任何第三方包。修改后的代码如下:
using System.IO.Compression; public string EditFile(IFormFile file, string nameOfnewDoc, string str1, string str2) { if (file == null) return "null"; var fileName = Path.GetFileName(file.FileName); var filePath = Path.Combine(_hostingEnv.WebRootPath, "docs", fileName); // 同步保存上传文件,避免异步没写完就读 using (var fileStream = new FileStream(filePath, FileMode.Create)) { file.CopyTo(fileStream); } var newFileBase = Path.Combine(_hostingEnv.WebRootPath, "docs", nameOfnewDoc); var fileExtension = Path.GetExtension(fileName).ToLowerInvariant(); if (fileExtension == ".doc") { // .doc改用Default编码,原UTF8可能导致内容乱码 string text = System.IO.File.ReadAllText(filePath, Encoding.Default); var newText = text.Replace(str1, str2); System.IO.File.WriteAllText(newFileBase + ".doc", newText, Encoding.Default); } else if (fileExtension == ".docx") { // 生成临时目录存解压后的内容 var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); Directory.CreateDirectory(tempDir); try { // 1. 把docx解压到临时目录 ZipFile.ExtractToDirectory(filePath, tempDir); // 2. 修改主文档的XML内容(核心文件是word/document.xml) var docXmlPath = Path.Combine(tempDir, "word", "document.xml"); if (File.Exists(docXmlPath)) { string xmlContent = File.ReadAllText(docXmlPath); // 替换目标字符串,注意XML里特殊字符会转义(比如&变成&) var newXmlContent = xmlContent.Replace(str1, str2); File.WriteAllText(docXmlPath, newXmlContent); } // 3. 把临时目录重新打包成docx ZipFile.CreateFromDirectory(tempDir, newFileBase + ".docx"); } finally { // 不管成功失败,都删临时目录 if (Directory.Exists(tempDir)) { Directory.Delete(tempDir, recursive: true); } } } return "success"; // 原返回"null"没意义,改成状态标识更合理 }
必看注意事项
- 别用异步
CopyToAsync:异步操作会让后续代码在文件还没完全保存时就去读,要么读错要么报错,换成同步CopyTo稳得多。 - .doc编码要改:原代码用UTF8读.doc会乱码,换成
Encoding.Default适配老格式。 - XML特殊字符处理:如果要替换的字符串里有&、<、>这些,得先转成XML实体(比如&→&)再替换,不然搜不到目标内容。
- 临时目录要删:每次生成唯一临时目录,用完就删,别占磁盘空间。
内容的提问来源于stack exchange,提问作者Haytham Tk
相关产品推荐
相关产品推荐

