System.IO.File.WriteAllBytes在上传.docx文档时出现问题。

huangapple go评论76阅读模式
英文:

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(&quot;.docx&quot;))
                {
                    contents.Append&lt;byte&gt;(addBytes[0]);
                    contents.Append&lt;byte&gt;(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 直接复制数据,使用 IFormFileCopyToAsync 方法。

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.

huangapple
  • 本文由 发表于 2023年6月8日 08:47:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76427945.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定