ASP.NET Core Pitfalls – Async File Uploads

When performing file upload(s) to an asynchronous action, it may happen that the uploaded file(s) may not be accessible, resulting in an ObjectDisposedException. This is because the uploaded files are saved to the filesystem temporarily by ASP.NET Core and then removed, after the request has been processed, which is generally what we want. If we issue an asynchronous task with an uploaded file and don’t wait for it to finish, it may happen that it occurs outside of the request’s scope, meaning, the uploaded file is already gone.

One way to address this is to have code like this:

[HttpPost]
public async Task<IActionResult> Upload(IFormFileCollection files)
{
    var f = files.ToArray();
    Array.ForEach(f, async (file) =>
    {
        using var stream = file.OpenReadStream();
        using var newStream = new MemoryStream();
        await stream.CopyToAsync(newStream);
        await ProcessFile(newStream);
    });
    return RedirectLocal("UploadSuccess");
}

For precaution, we make a copy of the original stream and use this copy instead in the upload processing code. I have successfully done this without the copy – which, of course, results in more memory usage, but occasionally I got errors as well. This way, I never had any problems.

                             

2 Comments

  • The Array.ForEach here is a bit tricky, something to watch out for. Since it's not async itself (it's expecting an Action<T>) it's actually using the "dangerous" async void pattern. This means that the actual code is immediately continued (eg. your return RedirectLocal might happen before the stream.CopyToAsync is finished).

    If you want to make sure that the memoryStreams are populated it might be better to use Task.WaitAll, for example
    var streams = await Task.WhenAll(f.Select(async (file) =>
    {
    using var stream = file.OpenReadStream();
    var newStream = new MemoryStream();
    await stream.CopyToAsync(newStream);
    return newStream;
    }).ToArray());

  • Does this change affects azure worker role?
    I am planning to start worker role project.
    Thanks

Add a Comment

As it will appear on the website

Not displayed

Your website