How to upload files in ASP.Net Core MVC

Take advantage of the IFormFile interface in ASP.Net Core MVC to upload small files, large files, and multiple files

How to upload files in ASP.Net Core MVC
Thinkstock

ASP.Net Core MVC provides support for uploading files through model binding that leverages the IFormFile interface. Recall that model binding maps data from an HTTP request to action method parameters. Model binding simplifies access to the data sent by an HTTP request and makes it easier for the action methods to be unit tested. The IFormFile interface simply represents a file sent with an HTTP request. 

We can take advantage of the IFormFile interface in our ASP.Net Core MVC applications to represent a file that is sent from the client to the server along with the HTTP request. This article presents a discussion of how we can upload files in ASP.Net Core MVC.

Create an ASP.Net Core MVC project

First off, let’s create an ASP.Net Core MVC project in Visual Studio. At the time of this writing, Visual Studio 2019 is available for free download. If you don’t have a copy of Visual Studio 2019 installed in your system, you can download it here

Next, follow the steps given below to create a new ASP.Net Core project in Visual Studio.

  1. Launch the Visual Studio IDE.
  2. Click on “Create new project.”
  3. In the “Create new project” window, select “ASP.Net Core Web Application” from the list of the templates displayed.
  4. Click Next. 
  5. In the “Configure your new project” window, specify the name and location for the new project.
  6. Click Create. 
  7. A new window, “Create New ASP.Net Core Web Application,” is shown next.
  8. Select .Net Core as the runtime and ASP.Net Core 2.2 (or later) from the drop-down list at the top.
  9. Select “Web Application (Model-View-Controller)” as the project template.
  10. Ensure that the check boxes “Enable Docker Support” and “Configure for HTTPS” are unchecked as we won’t be using those features here.
  11. Ensure that Authentication is set as “No Authentication” as we won’t be using authentication either.
  12. Click Create.

This will create a new ASP.Net Core MVC project in Visual Studio 2019. Now we’re ready to start coding. 

Upload a single file in ASP.Net Core MVC

In this section we’ll examine how we can take advantage of the IFormFile interface in the Microsoft.AspNetCore.Http namespace to upload one or more files. Here’s what the IFormFile interface looks like.

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);
}

In the Solution Explorer window of the newly created project, create a new controller named FileUploadController and write the following action method to upload a file.

[HttpPost("UploadFile")]
        public async Task<IActionResult> UploadFile
        (IFormFile iFormFile)
        {
            if (iFormFile == null || iFormFile.Length == 0)
                return ContentResult("No file selected for upload.");
            var filePath = Path.GetTempFileName();
            using (var stream = new FileStream(filePath,
            FileMode.Create))
            {
                await iFormFile.CopyToAsync(stream);
            }
            return RedirectToAction("Home");
        }

The action method accepts a reference to IFormFile as a parameter. It checks if this reference is null or the length of the file is zero. In either case, the processing is ignored and the method returns ContentResult with the text message “No file selected for upload.” Otherwise, the GetTempFileName method returns a temporary file name.

Next, a FileStream object is used to create a file and the CopyToAsync method is called on the IFormFile instance to asynchronously copy the contents of the uploaded file to the target stream.

Upload multiple files in ASP.Net Core MVC

When you are trying to upload a single file, your action method can include an IFormFile reference as a parameter. If you want to upload multiple files, you should use IEnumerable<IFormFile> or List<IFormFile> as a parameter to represent several files.

In the following example, the UploadFiles action method accepts a generic list of IFormFile as parameter.

[HttpPost("UploadFiles")]
public async Task<IActionResult> UploadFiles(List<IFormFile> iFormFiles)
{
    var filePath = Path.GetTempFileName();
    foreach (var iFormFile in iFormFiles)
    {
        if (iFormFile.Length > 0)
        {
            using (var stream = new FileStream(filePath,
            FileMode.Create))
            {
                await iFormFile.CopyToAsync(stream);
            }
        }
    }
    return RedirectToAction("Home");
}

Note that the action method here uses the GetTempFileName method, which throws an exception if the number of temporary files exceeds 65535. So, if you will be uploading more than 65535 files, you should either delete temporary files after you process them, or use the GetTempPath and the GetRandomFileName methods to create temporary file names.

Download a file using ASP.Net Core MVC

To download a file, you can use the following code.

public async Task<IActionResult> DownloadFile
(string path, string filename)
        {
            if (filename == null || filename.Length == 0)
                return Content
                ("No file selected for download.");
            var filePath = Path.Combine(path, filename);
            var memoryStream = new MemoryStream();
            using (var stream = new FileStream
            (filePath, FileMode.Open))
            {
                await stream.CopyToAsync(memoryStream);
            }
            memoryStream.Position = 0;
            return File(memoryStream, "text/plain",
            Path.GetFileName(path));
        }

The DownloadFile method uses the CopyToAsync method to copy the contents of the file to a memory stream object. It then returns an instance of FileStreamResult by specifying the appropriate content type of the file to be downloaded. In this example, we have hard-coded the content type as "text/plain" for simplicity.

Create a Razor view in ASP.Net Core MVC

Let’s now create an HTML view to upload one or more files. Select the Views solution folder in the Solution Explorer window, create a new Razor view page, and add the following code to it.

<form asp-controller="FileUpload" asp-action="UploadFile" method="post"
      enctype="multipart/form-data">
    <input type="file" name="file" />
    <button type="submit">Upload File</button>
</form>
<form asp-controller="FileUpload" asp-action="UploadFiles" method="post"
      enctype="multipart/form-data">
    <input type="file" name="files" multiple />
    <button type="submit">Upload Files</button>
</form>

Note that your HTML form should have the encoding type set as "multipart/form-data". There should also be one or more input elements having the type attribute set to "file" and pointing to the action method(s). If there are multiple files to be uploaded, the input element should have the multiple attribute set. The enctype attribute is used to specify how the form-data will be encoded when a post request is sent from the client to the server.

ASP.Net Core MVC provides excellent support for model binding, which can be leveraged to upload one or more files with small or large sizes. We’ll explore file uploads and downloads in ASP.Net Core in more detail in a later article here. 

Copyright © 2019 IDG Communications, Inc.