You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 04:25:17