Ajax Upload File Mvc Alonag With Data
In this article, let's go through one of the most searched queries on Google, "File Upload in ASP.NET Core MVC". Uploading Images or other documents is a very basic and common requirement when information technology comes to building anything from a uncomplicated awarding to an enterprise-level solution. Permit's build a modest awarding with which you could upload files of any type to a file arrangement location or to a centralized database table.
File Upload is quite important for any kind of application, right from saving a User'due south Profile Picture to storing some important documents. Files can be uploaded to either the Server'south Storage or to a Centralized Database. You can notice the completed source code on my GitHub Repo.
What we volition be building?
In this guide, We volition build together an ASP.NET Core MVC awarding that can upload files to both disk and database. In this fashion, we will get to encounter the entire process backside the build and add certain actress features along the manner. I volition be using Visual Studio 2019 Community as my IDE.
Setting up the ASP.NET Cadre MVC Project
Open upward VS and create a new ASP.Internet Cadre three.1 Application with the MVC (Model-View-Controller) Templated Web Application. As our data access layer, nosotros will use the Entity Framework Cadre (Code First Approach) as our ORM as it is pretty neat and efficient to fix up.
File Model
We know beforehand, that nosotros will exist uploading to either the deejay or to a database. Hence we volition need two Models. These 2 models will have virtually the same properties like file name, extension, created on, description, etc. These models will just vary at the post-obit 2 properties.
- File Path – This holding will be used by the model that is responsible to agree the details of the file that is on the disk.
- File Information – Whereas this belongings will be needed but for the model related to file in the database, as we will be converting the file to a byte assortment and storing this assortment to the data source,
Therefore, nosotros volition build an abstract course that has the mutual properties. Allow's call information technology FileModel.
Create a new grade, Models/FileModel.cs. This will be the base class.
public abstract form FileModel { public int Id { go; set; } public string Proper noun { get; set; } public string FileType { get; set; } public string Extension { get; set; } public cord Description { get; gear up; } public cord UploadedBy { become; set; } public DateTime? CreatedOn { get; set; } }
Now, permit's create a model for the file on the file system. Name it Models/FileOnFileSystem.cs and inherit the FileModel course.
public class FileOnFileSystemModel : FileModel { public cord FilePath { go; ready; } }
Similarly add some other class for the file on database, Models/FileOnDatabaseModel.cs
public class FileOnDatabaseModel : FileModel { public byte[] Information { get; ready; } }
Now that we have built our models, let's connect it to a database via Entity Framework Core.
Setting upward Entity Framework Core
New to Entity Framework Core – Code First Arroyo?
Read the detailed guide on Getting Started with Entity Framework Core in ASP.Internet Cadre Applications. This will cover nearly everything you need to know almost this awesome ORM.
Start, install these packages via Parcel Managing director Panel.
Install-Package Microsoft.EntityFrameworkCore Install-Packet Microsoft.EntityFrameworkCore.Design Install-Package Microsoft.EntityFrameworkCore.Tools Install-Bundle Microsoft.EntityFrameworkCore.SqlServer
Side by side, add a connection cord to your appsetting.json file.
"ConnectionStrings": { "DefaultConnection": "<Your Connectedness Cord Here>" }
With that out of of the way, let'south now configure the services. Modify the Startup.cs/ConfigureServices.
services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"), b => b.MigrationsAssembly(typeof(ApplicationDbContext).Associates.FullName)));
Finally, let'southward do the required migrations and update our database. Just run the following commands on the Parcel Manager Console.
add-migration Initial update-database
Yous volition get a done message on console. Open upwards SQL Server Object Explorer to check if the database and tables have been created.
What is IFormFile?
ASP.Internet Core has a built in interface that facilitates file upload.
Every bit you can see, IFormFile has several backdrop like Name, 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 listing of files to a list of IFormFile interface. From here, we will practise the uploading role of C#. Let'due south begin by creating a new empty MVC Controller, Controllers/FileController. Now let's add an associated view to this controller by right-clicking the index method.
Setting up the View and ViewModel
What'due south a View Model?
To the View (the UI, Alphabetize.cshtml), we need to pass two models at a fourth dimension. Nonetheless, by default we tin pass simply a single model to any given view. This requirement brought about ViewModels. ViewModels are simple classes that have multiple classes and backdrop inside them. For case, in this case, nosotros need to pass a list of FileOnFileSystemModel and FileOnDatabaseModel to our view. Hence, we make a new class, a ViewModel form, Models/FileUploadViewModel.cs as below.
public course FileUploadViewModel { public Listing<FileOnFileSystemModel> FilesOnFileSystem { get; set; } public List<FileOnDatabaseModel> FilesOnDatabase { get; set; } }
Afterwards that, Permit's starting time modifying the View Page, Views/File/Index.cshtml.
@model FileUploadViewModel @{ ViewData["Title"] = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h4>Start Uploading Files Here</h4> <60 minutes /> @if (ViewBag.Bulletin != null) { <div class="alert alert-success alert-dismissible" way="margin-top:20px"> @ViewBag.Message </div> } <form method="mail" enctype="multipart/grade-data"> <input type="file" proper name="files" multiple required /> <input blazon="text" autocomplete="off" placeholder="Enter File Description" name="description" required /> <button type="submit" class="btn btn-primary" asp-controller="File" asp-action="UploadToFileSystem">Upload to File Organisation</button> <button form="btn btn-success" type="submit" asp-controller="File" asp-activity="UploadToDatabase">Upload to Database</push> </form>
Line 1 – Hither nosotros define the available model as the created view model.
Lines eight-12 is for displaying a message/status if whatsoever exists.
Line 13 is the grade tag with the method equally Mail and enctype aspect as multipart/class-information. PS this is mandatory for making forms that let file upload.
Line 14 – an Input field of type file, with the proper noun files (this name will be used in our controllers, brand sure you enter this proper name), an attribute that says we are going to upload multiple files at one time and finally a required attribute.
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's go through the 2 dissimilar models of file upload.
File Upload in ASP.Cyberspace Cadre MVC to File System
Edit the Index.cshtml and add these lines of code.
<hr /> <h4>Files on File Organization</h4> @if (Model.FilesOnFileSystem.Count == 0) { <caption>No Records Found</caption> } else { <caption>List of Files on File Organisation</caption> <tabular array class="table table-striped"> <thead> <tr> <th>#</th> <th>Name</th> <thursday>Description</th> <th>File Blazon</th> <th>Created On</th> <th>Actions</thursday> </tr> </thead> <tbody> @foreach (var file in Model.FilesOnFileSystem) { <tr> <th>@file.Id</th> <td>@file.Proper name</td> <td>@file.Description</td> <td>@file.FileType</td> <td>@file.CreatedOn</td> <td> <a blazon="button" grade="btn btn-primary" asp-controller="File" asp-action="DownloadFileFromFileSystem" asp-road-id="@file.Id">Download</a> <a type="button" class="btn btn-danger" asp-controller="File" asp-activity="DeleteFileFromFileSystem" asp-route-id="@file.Id">Delete</a> </td> </tr> } </tbody> </table> }
Line 3-6, If no records institute in the FileOnFileSystem model, display a "No Records Found" message.
Line 7-38, else display the data within a bootstrap table.
Line 22-35, iterate over the list of bachelor 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 volition invoke a method from our File controller.
File Controller
Navigate to FileController. Make certain that you inject the ApplicaitonDbContext to the constructor of the FileController.
private readonly ApplicationDbContext context; public FileController(ApplicationDbContext context) { this.context = context; }
Initially, nosotros will need a method that returns a View Model, FileUploadViewModel. This method will be used by the other functions in the controllers. We will call the method, LoadAllFiles.
PS, you would probably want to put such methods exterior the controller, mayhap in a service layer. But to continue this demonstration uncomplicated, we will add all the required functions inside the controller. You could refactor the code as you would want .
private async Task<FileUploadViewModel> LoadAllFiles() { var viewModel = new FileUploadViewModel(); viewModel.FilesOnDatabase = await context.FilesOnDatabase.ToListAsync(); viewModel.FilesOnFileSystem = expect context.FilesOnFileSystem.ToListAsync(); render viewModel; }
Change the Index Method as follows.
public async Task<IActionResult> Index() { var fileuploadViewModel = await LoadAllFiles(); ViewBag.Bulletin = TempData["Bulletin"]; return View(fileuploadViewModel); }
Hither, we are loading all the available files and passing the View Model to the View.
Let's get started with the bodily Action Method that uploads the file(s) to the Disk. Add a new HTTPost Activeness method that takes in a listing of IFormFile (ensure that you name it files, equally we take given the same name in the html part also) and description string.
[HttpPost] public async Chore<IActionResult> UploadToFileSystem(List<IFormFile> files, cord 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)) { wait 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 together(fileModel); context.SaveChanges(); } } TempData["Message"] = "File successfully uploaded to File System."; return RedirectToAction("Alphabetize"); }
Line 6 – Gets the base of operations Path, i.e, The Electric current Directory of the application + /Files/. Feel free to alter this to your pick.
Line seven and 8 – Checks if the base of operations path directory exists, else creates it.
Line 9 – Gets the file proper name without the extension.
Line 10 – Combines the base of operations path with the file name.
Line xi – Gets the extension of the file. (*.png, *.mp4, etc)
Line xiv-17, If the file doesnt be in the generated path, nosotros use a filestream object, and create a new file, and then copy 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 case of efcore.
Line 31 – Loads all the File information to an object.
Line 32 – Sets a message in the TempData.
Line 33 – Redirects to the Index Action Method.
At present allow's work on the 2 button click activeness methods, download and delete.
public async Task<IActionResult> DownloadFileFromFileSystem(int id) { var file = await context.FilesOnFileSystem.Where(x => x.Id == id).FirstOrDefaultAsync(); if (file == zippo) return null; var retention = new MemoryStream(); using (var stream = new FileStream(file.FilePath, FileMode.Open up)) { await stream.CopyToAsync(retentiveness); } memory.Position = 0; return File(retentiveness, file.FileType, file.Name + file.Extension); }
DownloadFileFromFileSystem – Takes in File Id as the param, gets the respective records from the context instance / fileonfilesystem table. Copies the file data from the file path to a memory object, and returns the file for download/view.
public async Chore<IActionResult> DeleteFileFromFileSystem(int id) { var file = await context.FilesOnFileSystem.Where(x => ten.Id == id).FirstOrDefaultAsync(); if (file == zilch) render zip; if (System.IO.File.Exists(file.FilePath)) { Organisation.IO.File.Delete(file.FilePath); } context.FilesOnFileSystem.Remove(file); context.SaveChanges(); TempData["Message"] = $"Removed {file.Proper name + file.Extension} successfully from File Arrangement."; return RedirectToAction("Index"); }
DeleteFileFromFileSystem – Similarly, gets the records and deletes the file from the file system. Later we keep to remove the corresponding record from the database as well. Finally, we redirect to the index method with a completed message.
Now let's run our application and navigate to ../file.
I will upload a random file, give it a description and click on the upload to file system button.
And then, that is done. Now let's check the bodily directory where it is supposed to be uploaded to.
It gets uploaded every bit nosotros wanted. With that, let'south get to uploading file to the database.
[et_pb_section fb_built="1″ _builder_version="4.four.7″ background_color="#f4f4f4″ custom_padding="0px||0px||truthful|false"][et_pb_row _builder_version="iv.4.7″][et_pb_column type="4_4″ _builder_version="4.four.7″][et_pb_signup mailchimp_list="iammukeshm|3db1835b47″ name_field="on" title="So Far So Good?" clarification="
Stay upward to date! Go all the latest & greatest articles / in depth Guides on .NET Core / ASP.Net Cadre 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's add a new Activeness Method (Mail) named UploadToDatabase that, similar to the previous method, takes in a list of iformfile and a description.
[HttpPost] public async Task<IActionResult> UploadToDatabase(Listing<IFormFile> files,string clarification) { 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 xvi-20 , Creates a new MemoryStream object , catechumen file to retentivity object and appends ito our model's object.
Else, this method is quite similar to our previous 1.
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 be overkill though.)
At present, add a method to Download the file from database.
public async Task<IActionResult> DownloadFileFromDatabase(int id) { var file = await context.FilesOnDatabase.Where(x => ten.Id == id).FirstOrDefaultAsync(); if (file == null) return null; return File(file.Data, file.FileType, file.Name+file.Extension); }
Here, nosotros return a file object with information technology's content exactly as it is in the database. Finally nosotros add our last method, to delete a record. It's a quite straight forward i.
public async Task<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."; return RedirectToAction("Index"); }
With that done, let'southward practice our final tests. Build and run the awarding. Navigate to ../File/
PS, You could add a new navigation link in the nav-menu to easily navigate to the File Controller.
I will add some sample data and clarification and click on uploadtodatabase button.
Pretty Absurd yeah ๐ The thought might be uncomplicated, but we have congenital a well-nigh to complete utility that tin potentially showcase your skills as a developer, especially for the guys who are simply getting started with ASP.NET Core MVC.
If you lot institute this article helpful, consider supporting,
Buy me a coffee
Summary
Nosotros have covered the most bones topic in all of ASP.NET Core MVC past building a pretty cool tool. I promise you all enjoyed this detailed guide on File Upload in ASP.NET Core MVC. Share it within your developer community to assist others as well. ๐ Here is the source code for the completed project. Happy Coding ๐
Source: https://codewithmukesh.com/blog/file-upload-in-aspnet-core-mvc/
0 Response to "Ajax Upload File Mvc Alonag With Data"
Publicar un comentario