C# 从SQL读取varbinary生成docx转HTML提示文件损坏如何解决
问题根源分析
你遇到的报错本质是生成的docx文件本身不符合OpenXML规范,微软Word自带损坏文件修复能力所以能打开查看,但OpenXML SDK的校验逻辑更严格,直接读取非标准文档就会触发file contains corrupted data错误。结合你的字段名pricing_discussion_ole判断,90%以上的概率是数据库存储的不是纯docx二进制,而是带OLE包装头的嵌入对象,你直接把完整二进制写入文件相当于在正常docx前加了一段无效的OLE头数据。
解决方案
步骤1:验证二进制数据结构
正常docx是ZIP压缩包,文件头固定为0x50 0x4B 0x03 0x04(ASCII码对应PK),你可以先打印读取到的二进制前10位,确认是否和标准docx头一致:
byte[] fullData = (byte[])dr[0]; // 打印前10位十六进制 Console.WriteLine(BitConverter.ToString(fullData.Take(10).ToArray()));
如果输出开头不是50-4B-03-04,就可以确认存在多余的OLE头,需要裁剪。
步骤2:修改docx写入逻辑,裁剪无效头
调整你的写入代码,自动识别有效docx的起始位置,只写入规范部分:
cmd.CommandText = "SELECT [pricing_discussion_ole] FROM [dbo].[Query] where deal_identifier='ARCGL00202020'"; using (SqlDataReader dr = cmd.ExecuteReader()) { while (dr.Read()) { // 一次性读取完整二进制,避免分段读取的偏移错误 byte[] fullData = (byte[])dr[0]; int docxStartOffset = -1; // 查找标准docx头的位置 for (int i = 0; i < fullData.Length - 4; i++) { if (fullData[i] == 0x50 && fullData[i+1] == 0x4B && fullData[i+2] == 0x03 && fullData[i+3] == 0x04) { docxStartOffset = i; break; } } if (docxStartOffset == -1) { throw new InvalidDataException("未找到有效docx数据"); } // 仅写入有效部分到文件 using (FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.Write, FileShare.None)) { fs.Write(fullData, docxStartOffset, fullData.Length - docxStartOffset); fs.Flush(); } } }
此时生成的docx打开时不会再弹出“不可读内容”提示。
步骤3:优化HTML转换代码(可选)
如果还是偶发文件锁导致的报错,可以修改转换代码直接读取文件流,避免独占锁问题:
// 用可读可共享的方式打开文件流,避免被其他进程占用导致报错 using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (WordprocessingDocument doc = WordprocessingDocument.Open(fs, false)) { HtmlConverterSettings settings = new HtmlConverterSettings() { PageTitle = "My Page Title" }; XElement html = HtmlConverter.ConvertToHtml(doc, settings); var result = html.ToStringNewLineOnAttributes(); }
内容的提问来源于stack exchange,提问作者Letoncse
相关产品推荐
相关产品推荐

