英文:
System.IO.File.WriteAllBytes issue when used for uploading .docx document
问题
我有这样的代码来接受来自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在.....中发现了无法读取的内容。您要恢复此文档的内容吗?如果信任此文档的来源,请单击是”。
有人知道如何使WriteAllByte正常工作而不触发该消息吗?此代码适用于其他格式,甚至某些.docx也可以正常打开。只有大多数.docx文件损坏。
英文:
I have code like this to accept file upload from 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);
}
}
the addBytes was supposed to fix the problem but it did not make any difference. When I'm trying to open the docx document, I'm still prompted with this message: "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" .
Does anyone know how to make WriteAllByte work without tripping that message? This code works with other formats, and even some .docx would open fine too. Only most .docx are corrupted
答案1
得分: 4
this.HttpContext.Request.ContentLength
是整个请求的长度。假设这是一个 multipart/form-data
请求,它的大小大于文件的大小,因为可能有多个文件,而且还包括边界和每个部分的头部。要获取文件的大小,请使用表单文件上的 Length
属性。
但实际上,这是不必要的。通常情况下,我不喜欢使用 File.WriteAllBytes
,除非你已经有一个字节数组作为输入,因为这意味着你将不得不将源数据复制到数组并将其保存在内存中,这对于大文件是不好的。只需使用 FileStream
直接复制数据,使用 IFormFile
的 CopyToAsync
方法。
foreach (var uploadedFile in uploadedFiles)
{
var fullPath = Path.Combine(uploadFolderName, uploadedFile.FileName);
using var stream = File.Open(fullPath, FileMode.Create, FileAccess.Write);
await uploadedFile.CopyToAsync(stream);
}
这样做更短、更清晰、更高效、更快。
英文:
this.HttpContext.Request.ContentLength
is the length of the entire request. Assuming this is a multipart/form-data
request, that is bigger than the size of the file, because, well there might be more than one file, and also it includes things like boundaries and the headers of each part. To get the size of the file, use the Length
property on the form file.
But really, this is unnecessary. In general, I don't like using File.WriteAllBytes
unless you already have a byte array as input, because then it means you'll have to copy your source data to an array and hold it in memory, which is bad for large files. Just use a FileStream
and directly copy the data, using IFormFile
's CopyToAsync
method.
foreach (var uploadedFile in uploadedFiles)
{
var fullPath = Path.Combine(uploadFolderName, uploadedFile.FileName);
using var stream = File.Open(fullPath, FileMode.Create, FileAccess.Write);
await uploadedFile.CopyToAsync(stream);
}
There. This is shorter, clearer, more efficient, and faster.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论