ASP.NET Core MVC is a powerful framework that makes building web applications fast and easy. In many real-world scenarios, users need to upload and download files to and from the server. In this article, we will build a simple application that provides file upload and file download functionality in ASP.NET Core MVC.

1. Setting up the Project

To begin, create a new ASP.NET Core MVC project using the .NET CLI or Visual Studio.

Using CLI

dotnet new mvc -n FileUploadDownloadApp
cd FileUploadDownloadApp

Using Visual Studio

2. Creating the Model

The next step is to create a model that represents the file to be uploaded. We will store the uploaded file in an IFormFile object.

public class FileUploadViewModel
{
    public IFormFile File { get; set; }
}

The IFormFile interface represents the uploaded file in the HTTP request.

3. Creating the Controller

The controller handles user requests to upload and download files. Create a new FileController with actions for file upload, file listing, and file download.

using Microsoft.AspNetCore.Mvc;
using System.IO;
using System.Threading.Tasks;
using FileUploadDownloadApp.Models;
using Microsoft.AspNetCore.Hosting;

public class FileController : Controller
{
    private readonly IWebHostEnvironment _environment;
    public FileController(IWebHostEnvironment environment)
    {
        _environment = environment;
    }
    // GET: File/Upload
    public IActionResult Upload()
    {
        return View();
    }
    // POST: File/Upload
    [HttpPost]
    public async Task<IActionResult> Upload(FileUploadViewModel model)
    {
        if (model.File != null && model.File.Length > 0)
        {
            // Define the upload folder
            string uploadPath = Path.Combine(_environment.WebRootPath, "uploads");
            // Create the folder if it doesn't exist
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }
            // Generate the file path
            string filePath = Path.Combine(uploadPath, model.File.FileName);
            // Save the file to the specified location
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await model.File.CopyToAsync(stream);
            }
            ViewBag.Message = "File uploaded successfully!";
        }
        return View();
    }
    // GET: File/ListFiles
    public IActionResult ListFiles()
    {
        string uploadPath = Path.Combine(_environment.WebRootPath, "uploads");
        if (!Directory.Exists(uploadPath))
        {
            return View(new List<string>());
        }
        var files = Directory.GetFiles(uploadPath).Select(Path.GetFileName).ToList();
        return View(files);
    }
    // GET: File/Download?filename=example.txt
    public IActionResult Download(string filename)
    {
        if (string.IsNullOrEmpty(filename))
        {
            return Content("Filename is not provided.");
        }
        string filePath = Path.Combine(_environment.WebRootPath, "uploads", filename);
        if (!System.IO.File.Exists(filePath))
        {
            return Content("File not found.");
        }
        byte[] fileBytes = System.IO.File.ReadAllBytes(filePath);
        return File(fileBytes, "application/octet-stream", filename);
    }
}

Breakdown

4. Creating Views

Upload View (Upload. cshtml)

@model FileUploadViewModel
<h2>Upload File</h2>
<form asp-action="Upload" enctype="multipart/form-data" method="post">
    <div class="form-group">
        <input type="file" asp-for="File" class="form-control" />
    </div>
    <button type="submit" class="btn btn-primary">Upload</button>
</form>
@if (ViewBag.Message != null)
{
    <p>@ViewBag.Message</p>
}

List Files View (ListFiles.cshtml)

@model List<string>
<h2>Uploaded Files</h2>
<table class="table">
    <thead>
        <tr>
            <th>File Name</th>
            <th>Download</th>
        </tr>
    </thead>
    <tbody>
    @foreach (var file in Model)
    {
        <tr>
            <td>@file</td>
            <td>
                <a asp-action="Download" asp-route-filename="@file" class="btn btn-success">Download</a>
            </td>
        </tr>
    }
    </tbody>
</table>

5. Navigation in Layout

To make file upload and download pages easily accessible, add links to these views in the main layout file (_Layout. cshtml).

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>@ViewData["Title"] - FileUploadDownloadApp</title>
    <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />
    <link rel="stylesheet" href="~/css/site.css" asp-append-version="true" />
    <link rel="stylesheet" href="~/FileUploadDownloadApp.styles.css" asp-append-version="true" />
</head>
<body>
    <header>
        <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">
            <div class="container">
                <a class="navbar-brand" asp-area="" asp-page="/Index">FileUploadDownloadApp</a>
                <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target=".navbar-collapse" aria-controls="navbarSupportedContent"
                        aria-expanded="false" aria-label="Toggle navigation">
                    <span class="navbar-toggler-icon"></span>
                </button>
                <div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-controller="Home" asp-action="Upload">Upload File</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-controller="Home" asp-action="ListFiles">List Files</a>
                        </li>
                    </ul>
                </div>
            </div>
        </nav>
    </header>
    <div class="container">
        <main role="main" class="pb-3">
            @RenderBody()
        </main>
    </div>

    <footer class="border-top footer text-muted">
        <div class="container">
            © 2024 - FileUploadDownloadApp - <a asp-area="" asp-page="/Privacy">Privacy</a>
        </div>
    </footer>

    <script src="~/lib/jquery/dist/jquery.min.js"></script>
    <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
    <script src="~/js/site.js" asp-append-version="true"></script>

    @await RenderSectionAsync("Scripts", required: false)
</body>
</html>

6. Running and Testing the Application

Once you've added the controller, views, and navigation links, run the application.

7. Security and Best Practices

When implementing file upload and download functionality, security should be a top priority.

8. GitHub Project Link

9. Output

Output

10. Conclusion

In this article, we built a simple ASP.NET Core MVC application to handle file upload and download. We covered the basics of creating models, controllers, and views and implemented security best practices to ensure the application remains secure.

With this knowledge, you can extend the application further, adding features such as progress bars, database storage for file metadata, or even Azure blob storage integration for handling larger files in cloud environments.