File Upload is the process of uploading files from the user’s system to the web application’s storage. ASP.NET Core MVC actions support uploading of one or more files using simple model binding.

We have covered the file upload support in ASP.NET Core Web API in detail in the article Uploading Files With .NET Core Web API and Angular. There we looked at how to upload a file using an angular app on the client-side and an ASP.NET Core Web API on the server-side.

In this article, we are going to look at how to achieve the same functionality in an ASP.NET Core MVC application.


VIDEO: Uploading Files with ASP.NET Core WEB API and Angular video.


If you’ve missed some of the previous articles in the series we recommend visiting the series page: ASP.NET Core MVC Series.

To download this article’s source code visit: File Upload in ASP.NET Core MVC.

This article is divided into the following sections:

Let’s get down to it.

Creating a File Input Control

To upload files, let’s create a new ASP.NET Core MVC application, new FileUploadController and design an HTML form with a file input control for the Index action:

<form method="post" enctype="multipart/form-data" asp-controller="FileUpload" asp-action="Index">
    <div class="form-group">
        <div class="col-md-10">
            <p>Upload one or more files using this form:</p>
            <input type="file" name="files" multiple />
        </div>
    </div>
    <div class="form-group">
        <div class="col-md-10">
            <input type="submit" value="Upload" />
        </div>
    </div>
</form>

In order to support file uploads, we must specify the enctype as multipart/form-data. The enctype attribute specifies how the form data should be encoded when submitting it to the server. The enctype attribute can be used only if the form method is POST.

The file input element supports uploading multiple files. By removing the multiple attribute on the input element, we can restrict it to support just a single file.

The Role of Model Binding

We can access the individual files uploaded to the application through Model Binding using the IFormFile interface. Model Binding in ASP.NET Core MVC maps data from HTTP requests to action method parameters. IFormFile represents a file that is sent with the HttpRequest and has the following structure:

public interface IFormFile
{
    string ContentType { get; }
    string ContentDisposition { get; }
    IHeaderDictionary Headers { get; }
    long Length { get; }
    string Name { get; }
    string FileName { get; }
    Stream OpenReadStream();
    void CopyTo(Stream target);
    Task CopyToAsync(Stream target, CancellationToken cancellationToken = null);
}

As a security consideration, We should never rely on or trust the FileName property without validation.

When uploading files using model binding and the IFormFile interface, the action method can accept either a single IFormFile or an IEnumerable<IFormFile> representing multiple files. We can loop through one or more uploaded files, save them to the local file system and then use the files as per our application’s logic:

public class FileUploadController : Controller
{
    ...

    [HttpPost("FileUpload")]
    public async Task<IActionResult> Index(List<IFormFile> files)
    {
        long size = files.Sum(f => f.Length);
                        
        var filePaths = new List<string>();
        foreach (var formFile in files)
        {
            if (formFile.Length > 0)
            {
                // full path to file in temp location
                var filePath = Path.GetTempFileName(); //we are using Temp file name just for the example. Add your own file path.
                filePaths.Add(filePath);

                using (var stream = new FileStream(filePath, FileMode.Create))
                {
                    await formFile.CopyToAsync(stream);
                }
            }
        }

        // process uploaded files
        // Don't rely on or trust the FileName property without validation.

        return Ok(new { count = files.Count, size, filePaths });
    }
}

Let’s place a breakpoint on the Index() method and run the application:

upload files screen

Once we choose files and click Upload, we can debug the code to see how files are uploaded to the server file system.

Here we just return the total number and size of files uploaded along with file paths.

Files uploaded using the IFormFile technique are buffered in memory or on disk on the webserver before being processed. Inside the action method, the IFormFile contents are accessible as a stream. In addition to the local file system, files can be streamed to Azure Blob storage or Entity Framework.

OK, that’s it for the file upload, let’s summarize what we’ve learned.

Conclusion

In this article we have learned the following topics:

  • Creating a file upload control in ASP.NET Core MVC Application
  • Utilize model binding to get the uploaded files
  • Read and copy files to stream

In the next part of this series, we’ll look at Dependency Injection in ASP.NET Core MVC.