0

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

Yogi
  • 410
  • 4
  • 16
  • 1
    You should probably show what `.ToByteArrayAsync()` is doing and why you're passing that value to this method -- Not clear why you're converting to byte instead of writing the source stream to a file stream – Jimi Jun 08 '23 at 01:00
  • Unrelated to your actual problem as far as I'm aware, but `.Append` doesn't change `contents` - it just returns an `IEnumerable` that happens to also have the value of `addBytes[0]` at the end of the enumeration. You're not capturing the return value so it might as well be a no-op. – ProgrammingLlama Jun 08 '23 at 02:01

1 Answers1

4

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.

Etienne de Martel
  • 34,692
  • 8
  • 91
  • 111