File Upload With Mvc 5 and Angular
In this article, allow'south become through one of the most searched queries on Google, "File Upload in ASP.NET Cadre MVC". Uploading Images or other documents is a very basic and mutual requirement when it comes to building annihilation from a simple awarding to an enterprise-level solution. Permit's build a small application with which y'all could upload files of whatsoever type to a file organization location or to a centralized database table.
File Upload is quite important for whatever kind of application, right from saving a User'south Profile Picture to storing some important documents. Files can be uploaded to either the Server'southward Storage or to a Centralized Database. Y'all can find the completed source lawmaking on my GitHub Repo.
What nosotros will be building?
In this guide, We will build together an ASP.Cyberspace Cadre MVC application that can upload files to both deejay and database. In this fashion, we will get to see the entire process behind the build and add certain extra features along the way. I will be using Visual Studio 2019 Community as my IDE.
Setting up the ASP.NET Core MVC Project
Open up upward VS and create a new ASP.NET Core three.i Application with the MVC (Model-View-Controller) Templated Spider web Application. Equally our data admission layer, we will employ the Entity Framework Core (Lawmaking Commencement Approach) as our ORM as it is pretty dandy and efficient to ready.
File Model
We know beforehand, that we will be uploading to either the disk or to a database. Hence we volition need 2 Models. These ii models volition accept about the aforementioned properties like file name, extension, created on, description, etc. These models will only vary at the following ii backdrop.
- File Path – This property will be used past the model that is responsible to hold the details of the file that is on the deejay.
- File Data – Whereas this belongings will be needed but for the model related to file in the database, every bit we volition be converting the file to a byte array and storing this array to the data source,
Therefore, we will build an abstract class that has the common properties. Let's telephone call it FileModel.
Create a new class, Models/FileModel.cs. This will be the base course.
public abstruse course FileModel { public int Id { become; set; } public string Name { get; set; } public cord FileType { become; set; } public string Extension { get; prepare; } public string Clarification { go; set up; } public string UploadedBy { get; set up; } public DateTime? CreatedOn { go; set; } }
Now, permit'due south create a model for the file on the file organization. Proper noun it Models/FileOnFileSystem.cs and inherit the FileModel class.
public class FileOnFileSystemModel : FileModel { public string FilePath { become; set; } }
Similarly add together another form for the file on database, Models/FileOnDatabaseModel.cs
public class FileOnDatabaseModel : FileModel { public byte[] Data { go; set; } }
Now that we have congenital our models, let's connect it to a database via Entity Framework Core.
Setting upwardly Entity Framework Core
New to Entity Framework Core – Lawmaking First Approach?
Read the detailed guide on Getting Started with Entity Framework Core in ASP.Net Core Applications. This will comprehend near everything you demand to know almost this crawly ORM.
Start, install these packages via Package Managing director Panel.
Install-Packet Microsoft.EntityFrameworkCore Install-Package Microsoft.EntityFrameworkCore.Design Install-Package Microsoft.EntityFrameworkCore.Tools Install-Packet Microsoft.EntityFrameworkCore.SqlServer
Adjacent, add a connection string to your appsetting.json file.
"ConnectionStrings": { "DefaultConnection": "<Your Connection String Hither>" }
With that out of of the way, let'due south now configure the services. Modify the Startup.cs/ConfigureServices.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Assembly.FullName)));
Finally, let'due south practice the required migrations and update our database. Just run the following commands on the Parcel Manager Console.
add-migration Initial update-database
Y'all will become a done message on panel. Open SQL Server Object Explorer to bank check if the database and tables have been created.
What is IFormFile?
ASP.NET Core has a congenital in interface that facilitates file upload.
As y'all tin see, IFormFile has several properties like Proper noun, FileName, ContentType and a few methods to Re-create the file data to a retention stream. So, the basic idea will be, a front end with a form Html tag that, on submit, click sends the list of files to a listing of IFormFile interface. From here, we volition do the uploading part of C#. Allow's begin by creating a new empty MVC Controller, Controllers/FileController. Now allow's add an associated view to this controller by right-clicking the alphabetize method.
Setting upwardly the View and ViewModel
What'south a View Model?
To the View (the UI, Index.cshtml), we demand to pass ii models at a fourth dimension. Nonetheless, past default we tin can pass simply a unmarried model to any given view. This requirement brought nigh ViewModels. ViewModels are simple classes that accept multiple classes and properties inside them. For example, in this case, we need to laissez passer a list of FileOnFileSystemModel and FileOnDatabaseModel to our view. Hence, nosotros make a new class, a ViewModel class, Models/FileUploadViewModel.cs equally below.
public class FileUploadViewModel { public Listing<FileOnFileSystemModel> FilesOnFileSystem { get; set; } public Listing<FileOnDatabaseModel> FilesOnDatabase { become; ready; } }
Subsequently that, Allow's first modifying the View Folio, Views/File/Index.cshtml.
@model FileUploadViewModel @{ ViewData["Title"] = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h4>Start Uploading Files Here</h4> <hr /> @if (ViewBag.Message != cypher) { <div class="alert alert-success alert-dismissible" mode="margin-top:20px"> @ViewBag.Bulletin </div> } <form method="post" enctype="multipart/form-data"> <input type="file" name="files" multiple required /> <input type="text" autocomplete="off" placeholder="Enter File Clarification" name="clarification" required /> <push type="submit" course="btn btn-chief" asp-controller="File" asp-action="UploadToFileSystem">Upload to File System</button> <button course="btn btn-success" type="submit" asp-controller="File" asp-activeness="UploadToDatabase">Upload to Database</button> </form>
Line 1 – Here nosotros define the available model equally the created view model.
Lines 8-12 is for displaying a bulletin/status if any exists.
Line 13 is the form tag with the method as Mail service and enctype aspect as multipart/course-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 volition 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 attribute.
Line fifteen – 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.
Side by side, let'due south go through the 2 dissimilar models of file upload.
File Upload in ASP.NET Core MVC to File Organization
Edit the Index.cshtml and add together these lines of code.
<hr /> <h4>Files on File Arrangement</h4> @if (Model.FilesOnFileSystem.Count == 0) { <caption>No Records Found</caption> } else { <explanation>Listing of Files on File System</caption> <table class="table table-striped"> <thead> <tr> <th>#</thursday> <th>Name</th> <thursday>Clarification</th> <thursday>File Type</th> <th>Created On</th> <th>Actions</th> </tr> </thead> <tbody> @foreach (var file in Model.FilesOnFileSystem) { <tr> <thursday>@file.Id</th> <td>@file.Name</td> <td>@file.Description</td> <td>@file.FileType</td> <td>@file.CreatedOn</td> <td> <a type="button" grade="btn btn-chief" asp-controller="File" asp-action="DownloadFileFromFileSystem" asp-route-id="@file.Id">Download</a> <a type="push" class="btn btn-danger" asp-controller="File" asp-action="DeleteFileFromFileSystem" asp-route-id="@file.Id">Delete</a> </td> </tr> } </tbody> </tabular array> }
Line 3-six, If no records found in the FileOnFileSystem model, brandish a "No Records Found" message.
Line 7-38, else display the information within a bootstrap table.
Line 22-35, iterate over the list of available records and add content to the table.
Line 31,32 Add action buttons to view the file and to delete the file from the deejay. These buttons will invoke a method from our File controller.
File Controller
Navigate to FileController. Brand sure that you lot 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, peradventure in a service layer. But to keep this demonstration simple, we volition add all the required functions inside the controller. You could refactor the lawmaking as yous would desire .
private async Task<FileUploadViewModel> LoadAllFiles() { var viewModel = new FileUploadViewModel(); viewModel.FilesOnDatabase = expect context.FilesOnDatabase.ToListAsync(); viewModel.FilesOnFileSystem = await context.FilesOnFileSystem.ToListAsync(); return viewModel; }
Change the Index Method as follows.
public async Task<IActionResult> Index() { var fileuploadViewModel = await LoadAllFiles(); ViewBag.Message = TempData["Bulletin"]; return View(fileuploadViewModel); }
Here, nosotros are loading all the bachelor files and passing the View Model to the View.
Let's get started with the actual Action Method that uploads the file(due south) to the Disk. Add a new HTTPost Action method that takes in a list of IFormFile (ensure that yous name it files, every bit we accept given the same name in the html part too) and description string.
[HttpPost] public async Task<IActionResult> UploadToFileSystem(Listing<IFormFile> files, cord description) { 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, Name = fileName, Description = clarification, FilePath = filePath }; context.FilesOnFileSystem.Add(fileModel); context.SaveChanges(); } } TempData["Message"] = "File successfully uploaded to File System."; return RedirectToAction("Index"); }
Line six – Gets the base of operations Path, i.e, The Current Directory of the application + /Files/. Feel gratuitous to change this to your choice.
Line 7 and 8 – Checks if the base path directory exists, else creates information technology.
Line 9 – Gets the file proper noun without the extension.
Line 10 – Combines the base path with the file name.
Line 11 – Gets the extension of the file. (*.png, *.mp4, etc)
Line 14-17, If the file doesnt exist in the generated path, we use a filestream object, and create a new file, and so copy the contents to information technology.
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 message in the TempData.
Line 33 – Redirects to the Index Action Method.
Now let'due south work on the ii button click activity methods, download and delete.
public async Job<IActionResult> DownloadFileFromFileSystem(int id) { var file = await context.FilesOnFileSystem.Where(10 => x.Id == id).FirstOrDefaultAsync(); if (file == null) return nil; var retention = new MemoryStream(); using (var stream = new FileStream(file.FilePath, FileMode.Open up)) { wait stream.CopyToAsync(memory); } memory.Position = 0; return File(memory, file.FileType, file.Name + file.Extension); }
DownloadFileFromFileSystem – Takes in File Id as the param, gets the corresponding records from the context example / fileonfilesystem table. Copies the file data from the file path to a retention object, and returns the file for download/view.
public async Job<IActionResult> DeleteFileFromFileSystem(int id) { var file = await context.FilesOnFileSystem.Where(x => x.Id == id).FirstOrDefaultAsync(); if (file == cipher) 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 System."; return RedirectToAction("Index"); }
DeleteFileFromFileSystem – Similarly, gets the records and deletes the file from the file system. Later we proceed to remove the corresponding record from the database also. Finally, we redirect to the alphabetize method with a completed message.
Now let's run our application and navigate to ../file.
I volition upload a random file, give it a clarification and click on the upload to file system button.
So, that is done. At present allow's bank check the actual directory where it is supposed to be uploaded to.
It gets uploaded equally we wanted. With that, let's go to uploading file to the database.
[et_pb_section fb_built="1″ _builder_version="4.four.vii″ background_color="#f4f4f4″ custom_padding="0px||0px||true|false"][et_pb_row _builder_version="4.iv.7″][et_pb_column blazon="4_4″ _builder_version="four.four.7″][et_pb_signup mailchimp_list="iammukeshm|3db1835b47″ name_field="on" title="Then Far And so Skilful?" description="
Stay upwards to engagement! Become all the latest & greatest manufactures / in depth Guides on .Net Core / ASP.Internet Core delivered straight to your inbox. Subscribe now!
" _builder_version="4.4.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
Let'southward add together a new Activity Method (POST) named UploadToDatabase that, similar to the previous method, takes in a list of iformfile and a description.
[HttpPost] public async Task<IActionResult> UploadToDatabase(List<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 = clarification }; using (var dataStream = new MemoryStream()) { await 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-twenty , Creates a new MemoryStream object , catechumen file to retention object and appends ito our model'due south object.
Else, this method is quite similar to our previous ane.
Further Improvement.
Information technology 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 blueprint pattern here. (Might be overkill though.)
Now, add a method to Download the file from database.
public async Task<IActionResult> DownloadFileFromDatabase(int id) { var file = await context.FilesOnDatabase.Where(x => x.Id == id).FirstOrDefaultAsync(); if (file == null) return null; render File(file.Data, file.FileType, file.Name+file.Extension); }
Here, we return a file object with information technology's content exactly every bit it is in the database. Finally we add our terminal method, to delete a record. It's a quite directly forward one.
public async Chore<IActionResult> DeleteFileFromDatabase(int id) { var file = await context.FilesOnDatabase.Where(x => x.Id == id).FirstOrDefaultAsync(); context.FilesOnDatabase.Remove(file); context.SaveChanges(); TempData["Message"] = $"Removed {file.Name + file.Extension} successfully from Database."; render RedirectToAction("Alphabetize"); }
With that washed, let's practice our final tests. Build and run the application. Navigate to ../File/
PS, You could add a new navigation link in the nav-menu to hands navigate to the File Controller.
I will add some sample data and clarification and click on uploadtodatabase button.
Pretty Cool aye 😀 The idea might be unproblematic, but we have built a almost to complete utility that can potentially showcase your skills as a developer, specially for the guys who are but getting started with ASP.Internet Cadre MVC.
If you plant this article helpful, consider supporting,
Buy me a java
Summary
We have covered the near basic topic in all of ASP.NET Cadre MVC past building a pretty cool tool. I hope you all enjoyed this detailed guide on File Upload in ASP.NET Core MVC. Share it within your developer customs 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/
0 Response to "File Upload With Mvc 5 and Angular"
Post a Comment