使用System.IO.File.WriteAllBytes上传.docx文档时出现损坏问题求助
问题:上传docx文件后打开提示损坏,如何修复?
我用以下代码接收Web UI上传的文件:
byte[] addBytes = new byte[] { 45, 45 }; var uploadedFiles = this.HttpContext.Request.Form.Files; foreach (var uploadedFile in uploadedFiles) { filename = uploadedFile.FileName; fileFullPath = Path.Combine(uploadFolderName, filename); using (Stream bodyStream = uploadedFile.OpenReadStream()) { byte[] contents = await bodyStream.ToByteArrayAsync((int)this.HttpContext.Request.ContentLength); if (filename.ToLower().EndsWith(".docx")) { contents.Append<byte>(addBytes[0]); contents.Append<byte>(addBytes[1]); } System.IO.File.WriteAllBytes(fileFullPath, contents); } }
原本想通过addBytes解决问题,但毫无效果。打开docx文档时仍弹出提示:
Word found unreadable content in ..... Do you want to recover the contents of this document? If you trust the source of this document, click Yes
这段代码对其他格式文件有效,部分docx也能正常打开,但多数docx文件会损坏。请问如何让WriteAllBytes正常工作,避免触发该提示?
解决方案
你的代码存在两个核心问题,导致docx文件损坏:
错误读取文件长度
你用this.HttpContext.Request.ContentLength作为文件流的读取长度,但这个值是整个HTTP请求的总长度,包含表单的其他字段数据,不是单个上传文件的实际长度。这会导致读取的字节数组要么截断,要么包含额外无效数据,直接破坏docx的zip格式结构,触发Word的修复提示。无效的数组操作
contents.Append<byte>(...)不会修改原数组——C#数组是固定长度的,Append方法返回的是新的枚举对象,你没有接收这个返回值,所以addBytes根本没被添加到文件内容里。而且就算成功添加,给docx文件末尾加两个减号也会破坏其zip结构,完全没必要这么做。
修复后的代码
直接将上传文件的流复制到目标文件,不需要转成byte数组,既避免长度错误,又节省内存:
var uploadedFiles = this.HttpContext.Request.Form.Files; foreach (var uploadedFile in uploadedFiles) { var filename = uploadedFile.FileName; var fileFullPath = Path.Combine(uploadFolderName, filename); // 直接复制流,避免错误的长度读取和数组操作 using (var stream = new FileStream(fileFullPath, FileMode.Create)) { await uploadedFile.CopyToAsync(stream); } }
额外注意事项
- 不要随意修改docx文件的字节内容:docx本质是压缩包,任何无关的字节修改都会破坏其结构,导致Word无法正常解析。
- 确保
uploadFolderName目录存在,否则会抛出异常,可以提前用Directory.CreateDirectory(uploadFolderName)创建目录。
内容的提问来源于stack exchange,提问作者Yogi
相关产品推荐
相关产品推荐

