Asp.net Core 2.2 Image Upload Using Mimemultipartcontent
In this commodity, let'due south go through ane of the almost searched queries on Google, "File Upload in ASP.NET Core MVC". Uploading Images or other documents is a very bones and common requirement when information technology comes to edifice anything from a uncomplicated application to an enterprise-level solution. Allow's build a minor awarding with which yous could upload files of any blazon to a file system location or to a centralized database tabular array.
File Upload is quite of import for whatsoever kind of awarding, right from saving a User's Profile Picture to storing some important documents. Files can exist uploaded to either the Server's Storage or to a Centralized Database. You tin can observe the completed source code on my GitHub Repo.
What we will be building?

In this guide, We will build together an ASP.NET Core MVC application that tin can upload files to both disk and database. In this way, we will get to encounter the entire process behind the build and add certain extra features forth the way. I will exist using Visual Studio 2019 Customs as my IDE.
Setting up the ASP.NET Core MVC Project
Open up VS and create a new ASP.NET Core three.1 Application with the MVC (Model-View-Controller) Templated Web Application. As our information admission layer, we will use the Entity Framework Core (Lawmaking Commencement Approach) every bit our ORM as it is pretty neat and efficient to prepare.
File Model
We know beforehand, that we will be uploading to either the disk or to a database. Hence we volition need two Models. These 2 models will take almost the aforementioned backdrop like file name, extension, created on, description, etc. These models will only vary at the post-obit two properties.
- File Path – This property will be used by the model that is responsible to hold the details of the file that is on the disk.
- File Information – Whereas this property volition be needed just for the model related to file in the database, every bit nosotros will be converting the file to a byte array and storing this array to the information source,
Therefore, we will build an abstract class that has the common properties. Let'due south call information technology FileModel.
Create a new class, Models/FileModel.cs. This will exist the base class.
public abstruse form FileModel { public int Id { go; set; } public cord Proper name { get; set; } public string FileType { get; set; } public string Extension { get; set; } public string Description { get; set; } public cord UploadedBy { go; set up; } public DateTime? CreatedOn { get; set; } }
Now, allow's create a model for the file on the file organization. Name it Models/FileOnFileSystem.cs and inherit the FileModel class.
public class FileOnFileSystemModel : FileModel { public string FilePath { become; set up; } }
Similarly add another class for the file on database, Models/FileOnDatabaseModel.cs
public form FileOnDatabaseModel : FileModel { public byte[] Data { get; fix; } }
Now that we accept built our models, let'due south connect it to a database via Entity Framework Core.
Setting up Entity Framework Core
New to Entity Framework Cadre – Code First Approach?
Read the detailed guide on Getting Started with Entity Framework Core in ASP.Cyberspace Core Applications. This will comprehend almost everything you lot need to know nearly this crawly ORM.
First, install these packages via Packet Manager Console.
Install-Package Microsoft.EntityFrameworkCore Install-Parcel Microsoft.EntityFrameworkCore.Design Install-Packet Microsoft.EntityFrameworkCore.Tools Install-Package Microsoft.EntityFrameworkCore.SqlServer
Next, add a connexion string to your appsetting.json file.
"ConnectionStrings": { "DefaultConnection": "<Your Connection Cord Here>" }
With that out of of the style, let'southward now configure the services. Alter the Startup.cs/ConfigureServices.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
Finally, permit'southward exercise the required migrations and update our database. Just run the following commands on the Package Manager Panel.
add-migration Initial update-database
You will get a done message on console. Open SQL Server Object Explorer to bank check if the database and tables have been created.

What is IFormFile?

ASP.NET Cadre has a built in interface that facilitates file upload.
Every bit you tin can see, IFormFile has several backdrop like Proper name, FileName, ContentType and a few methods to Copy the file information to a retention stream. So, the bones idea will be, a front stop with a form Html tag that, on submit, click sends the listing of files to a list of IFormFile interface. From here, we volition practice the uploading function of C#. Let's begin past creating a new empty MVC Controller, Controllers/FileController. Now let'southward add together an associated view to this controller by right-clicking the index method.

Setting upwardly the View and ViewModel
What's a View Model?
To the View (the UI, Index.cshtml), we demand to pass 2 models at a time. Withal, by default we tin can pass only a single model to any given view. This requirement brought about ViewModels. ViewModels are simple classes that have multiple classes and backdrop within them. For example, in this instance, nosotros need to pass a list of FileOnFileSystemModel and FileOnDatabaseModel to our view. Hence, we brand a new class, a ViewModel class, Models/FileUploadViewModel.cs as below.
public class FileUploadViewModel { public List<FileOnFileSystemModel> FilesOnFileSystem { get; set; } public List<FileOnDatabaseModel> FilesOnDatabase { become; set; } }
Subsequently that, Let's starting time modifying the View Page, Views/File/Index.cshtml.
@model FileUploadViewModel @{ ViewData["Title"] = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h4>Outset Uploading Files Here</h4> <hr /> @if (ViewBag.Bulletin != null) { <div course="alarm alert-success alert-dismissible" style="margin-top:20px"> @ViewBag.Message </div> } <form method="mail service" enctype="multipart/grade-data"> <input type="file" proper noun="files" multiple required /> <input type="text" autocomplete="off" placeholder="Enter File Clarification" proper noun="clarification" required /> <button type="submit" class="btn btn-primary" asp-controller="File" asp-action="UploadToFileSystem">Upload to File Organization</push> <push class="btn btn-success" type="submit" asp-controller="File" asp-action="UploadToDatabase">Upload to Database</button> </course>
Line 1 – Here we define the bachelor model as the created view model.
Lines viii-12 is for displaying a message/status if whatever exists.
Line 13 is the form tag with the method as POST and enctype attribute every bit multipart/form-data. PS this is mandatory for making forms that allow file upload.
Line 14 – an Input field of type file, with the name files (this name will be used in our controllers, make sure you enter this proper name), an attribute that says we are going to upload multiple files at once and finally a required aspect.
Line 15 – A text field for Description. Mandatory.
Line 16 and 17 are buttons of the type submit that invoke the FILE/{Method} Controller to upload the file(s) to DB/disk.
Next, let'southward go through the 2 dissimilar models of file upload.
File Upload in ASP.Net Core MVC to File Arrangement
Edit the Index.cshtml and add together these lines of code.
<hour /> <h4>Files on File Organisation</h4> @if (Model.FilesOnFileSystem.Count == 0) { <caption>No Records Found</explanation> } else { <caption>List of Files on File System</caption> <table class="table table-striped"> <thead> <tr> <th>#</th> <th>Name</th> <thursday>Clarification</th> <thursday>File Blazon</th> <thursday>Created On</th> <thursday>Actions</th> </tr> </thead> <tbody> @foreach (var file in Model.FilesOnFileSystem) { <tr> <th>@file.Id</th> <td>@file.Name</td> <td>@file.Description</td> <td>@file.FileType</td> <td>@file.CreatedOn</td> <td> <a type="push" class="btn btn-primary" asp-controller="File" asp-action="DownloadFileFromFileSystem" asp-route-id="@file.Id">Download</a> <a type="button" class="btn btn-danger" asp-controller="File" asp-activeness="DeleteFileFromFileSystem" asp-route-id="@file.Id">Delete</a> </td> </tr> } </tbody> </table> }
Line three-six, If no records found in the FileOnFileSystem model, brandish a "No Records Constitute" message.
Line 7-38, else brandish the data inside a bootstrap table.
Line 22-35, iterate over the listing of available records and add content to the table.
Line 31,32 Add activeness buttons to view the file and to delete the file from the disk. These buttons will invoke a method from our File controller.
File Controller
Navigate to FileController. Make certain that yous inject the ApplicaitonDbContext to the constructor of the FileController.
individual readonly ApplicationDbContext context; public FileController(ApplicationDbContext context) { this.context = context; }
Initially, we volition demand a method that returns a View Model, FileUploadViewModel. This method volition exist used by the other functions in the controllers. We will call the method, LoadAllFiles.
PS, you would probably want to put such methods outside the controller, maybe in a service layer. But to continue this sit-in simple, we volition add all the required functions within the controller. You could refactor the code every bit you would want .
private async Task<FileUploadViewModel> LoadAllFiles() { var viewModel = new FileUploadViewModel(); viewModel.FilesOnDatabase = look context.FilesOnDatabase.ToListAsync(); viewModel.FilesOnFileSystem = await context.FilesOnFileSystem.ToListAsync(); return viewModel; }
Change the Index Method as follows.
public async Chore<IActionResult> Index() { var fileuploadViewModel = await LoadAllFiles(); ViewBag.Message = TempData["Bulletin"]; return View(fileuploadViewModel); }
Here, we are loading all the available files and passing the View Model to the View.
Let's go started with the actual Action Method that uploads the file(s) to the Disk. Add together a new HTTPost Action method that takes in a listing of IFormFile (ensure that yous name it files, as nosotros take given the same name in the html part too) and description string.
[HttpPost] public async Job<IActionResult> UploadToFileSystem(Listing<IFormFile> files, string clarification) { foreach(var file in files) { var basePath = Path.Combine(Directory.GetCurrentDirectory() + "\\Files\\"); bool basePathExists = System.IO.Directory.Exists(basePath); if (!basePathExists) Directory.CreateDirectory(basePath); var fileName = Path.GetFileNameWithoutExtension(file.FileName); var filePath = Path.Combine(basePath, file.FileName); var extension = Path.GetExtension(file.FileName); if (!System.IO.File.Exists(filePath)) { using (var stream = new FileStream(filePath, FileMode.Create)) { await file.CopyToAsync(stream); } var fileModel = new FileOnFileSystemModel { CreatedOn = DateTime.UtcNow, FileType = file.ContentType, Extension = extension, Proper noun = fileName, Description = description, FilePath = filePath }; context.FilesOnFileSystem.Add(fileModel); context.SaveChanges(); } } TempData["Message"] = "File successfully uploaded to File Organisation."; render RedirectToAction("Index"); }
Line 6 – Gets the base of operations Path, i.e, The Electric current Directory of the awarding + /Files/. Feel gratis to modify this to your option.
Line 7 and viii – Checks if the base of operations path directory exists, else creates it.
Line 9 – Gets the file proper noun without the extension.
Line ten – Combines the base path with the file name.
Line xi – Gets the extension of the file. (*.png, *.mp4, etc)
Line xiv-17, If the file doesnt exist in the generated path, nosotros use a filestream object, and create a new file, and and then re-create the contents to it.
Line 18-26, Create a new FileOnFileSystemModel object with required values.
Line 27 and 28, Inserts this model to the db via the context instance of efcore.
Line 31 – Loads all the File data to an object.
Line 32 – Sets a bulletin in the TempData.
Line 33 – Redirects to the Index Action Method.
At present let's piece of work on the ii push click action methods, download and delete.
public async Chore<IActionResult> DownloadFileFromFileSystem(int id) { var file = wait context.FilesOnFileSystem.Where(10 => 10.Id == id).FirstOrDefaultAsync(); if (file == nothing) return null; var memory = new MemoryStream(); using (var stream = new FileStream(file.FilePath, FileMode.Open)) { await stream.CopyToAsync(retentiveness); } memory.Position = 0; render File(memory, file.FileType, file.Name + file.Extension); }
DownloadFileFromFileSystem – Takes in File Id every bit the param, gets the corresponding records from the context example / fileonfilesystem tabular array. Copies the file data from the file path to a retentiveness object, and returns the file for download/view.
public async Task<IActionResult> DeleteFileFromFileSystem(int id) { var file = look context.FilesOnFileSystem.Where(x => x.Id == id).FirstOrDefaultAsync(); if (file == cypher) return null; if (Arrangement.IO.File.Exists(file.FilePath)) { System.IO.File.Delete(file.FilePath); } context.FilesOnFileSystem.Remove(file); context.SaveChanges(); TempData["Message"] = $"Removed {file.Proper name + file.Extension} successfully from File Organisation."; return RedirectToAction("Index"); }
DeleteFileFromFileSystem – Similarly, gets the records and deletes the file from the file organisation. Afterward we proceed to remove the respective record from the database as well. Finally, we redirect to the index method with a completed message.
At present let'south run our awarding and navigate to ../file.

I volition upload a random file, give it a clarification and click on the upload to file system push button.

So, that is done. At present let'due south cheque the actual directory where it is supposed to be uploaded to.

It gets uploaded as we wanted. With that, let'south go to uploading file to the database.
[et_pb_section fb_built="1″ _builder_version="4.4.vii″ background_color="#f4f4f4″ custom_padding="0px||0px||true|false"][et_pb_row _builder_version="4.4.vii″][et_pb_column type="4_4″ _builder_version="4.iv.7″][et_pb_signup mailchimp_list="iammukeshm|3db1835b47″ name_field="on" title="And then Far And then Good?" description="
Stay upwards to date! Get all the latest & greatest articles / in depth Guides on .NET Core / ASP.NET Core delivered straight to your inbox. Subscribe at present!
" _builder_version="4.iv.7″ header_font="||||||||" background_enable_color="off" custom_button="on" button_text_color="#ffffff" button_bg_color="#00a7e1″ button_border_width="0px" background_layout="light" button_bg_color__hover_enabled="on|hover" button_bg_color__hover="#2176ae" button_bg_enable_color__hover="on"][/et_pb_signup][/et_pb_column][/et_pb_row][/et_pb_section]
File Upload in ASP.Net Core MVC to Database
Permit'south add a new Activity Method (Post) named UploadToDatabase that, like to the previous method, takes in a listing of iformfile and a description.
[HttpPost] public async Task<IActionResult> UploadToDatabase(Listing<IFormFile> files,string description) { foreach (var file in files) { var fileName = Path.GetFileNameWithoutExtension(file.FileName); var extension = Path.GetExtension(file.FileName); var fileModel = new FileOnDatabaseModel { CreatedOn = DateTime.UtcNow, FileType = file.ContentType, Extension = extension, Name = fileName, Clarification = description }; using (var dataStream = new MemoryStream()) { wait file.CopyToAsync(dataStream); fileModel.Data = dataStream.ToArray(); } context.FilesOnDatabase.Add(fileModel); context.SaveChanges(); } TempData["Message"] = "File successfully uploaded to Database"; return RedirectToAction("Index"); }
Line 16-20 , Creates a new MemoryStream object , catechumen file to memory object and appends ito our model's object.
Else, this method is quite similar to our previous one.
Further Improvement.
It is possible to refactor this method and make a common method or something, just to reduce the lines of code. Or you could probably implement a design pattern here. (Might exist overkill though.)
Now, add a method to Download the file from database.
public async Chore<IActionResult> DownloadFileFromDatabase(int id) { var file = await context.FilesOnDatabase.Where(x => x.Id == id).FirstOrDefaultAsync(); if (file == cypher) return cypher; return File(file.Data, file.FileType, file.Name+file.Extension); }
Hither, we return a file object with it's content exactly equally it is in the database. Finally we add our last method, to delete a record. It'south a quite straight frontwards ane.
public async Task<IActionResult> DeleteFileFromDatabase(int id) { var file = await context.FilesOnDatabase.Where(ten => x.Id == id).FirstOrDefaultAsync(); context.FilesOnDatabase.Remove(file); context.SaveChanges(); TempData["Message"] = $"Removed {file.Proper name + file.Extension} successfully from Database."; return RedirectToAction("Index"); }
With that done, let'southward do our final tests. Build and run the application. Navigate to ../File/
PS, You could add a new navigation link in the nav-menu to easily navigate to the File Controller.

I volition add some sample information and description and click on uploadtodatabase push.

Pretty Cool yeah 😀 The idea might be uncomplicated, but we have congenital a near to complete utility that tin can potentially showcase your skills as a programmer, especially for the guys who are but getting started with ASP.NET Core MVC.
If you establish this article helpful, consider supporting,
Buy me a coffee
Summary
We have covered the virtually basic topic in all of ASP.Internet Cadre MVC by building a pretty cool tool. I hope yous all enjoyed this detailed guide on File Upload in ASP.Cyberspace Cadre MVC. Share information technology within your developer community to aid others as well. 😀 Here is the source lawmaking for the completed project. Happy Coding 😀
Source: https://codewithmukesh.com/blog/file-upload-in-aspnet-core-mvc/
Post a Comment for "Asp.net Core 2.2 Image Upload Using Mimemultipartcontent"