ASP.NET MVC 5 - Upload Image/File Into Database

This article is about uploading of the image file into the database on ASP.NET MVC5 platform. I shall be demonstrating uploading of the image file into the database on ASP.NET MVC5 platform. This article is not specific to image file only, you can use the provided solution with any type of file format as well.

Collecting image data or any other file format data is equally important as collecting textual data. Although collecting textual data is more simple than collecting an image or any other file format data, the choice for storing the image or any other file format data is the most difficult part, but, it entirely depends on one's business & system requirement.

Today, I shall be demonstrating uploading of the image file into the database on ASP.NET MVC5 platform. This article is not specific to image files only, you can use the provided solution with any type of file format as well.

ASP.NET MVC 5 - Upload Image/File Into Database

Before moving to the coding part, let us observe some of the advantages and disadvantages of uploading an image or any other file format data into the database.

Advantages (Pros)
  1. Sensitive images or any other file format data is fully secure as it is only accessible via system/software. Files are not accessible via links.
  2. Storing of the uploaded file is guaranteed.
  3. Images/Files store on database do not require extra backups.
  4. Transnational integrity is guaranteed as you won't be locked into typical reader/writer problem and deleting the entry in the database means the file is actually deleted, you do not need extra precautions to delete the file i.e. ensuring that file is deleted from both database and file system.
  5. Image replication is easy (if needed).
  6. In load-balanced web servers or distributed environments, dealing with synchronizing images across multiple file systems is difficult especially in a web application where a new server may be added any time.

Disadvantages (Cons)

  1. Database storage becomes expensive for many and large file storage.
  2. There will be a performance penalty as latency to retrieve image/file is slower and database lookup is slower than filesystem lookup.
  3. Additional code is needed to extract and stream files.
  4. You cannot directly edit the files, especially images files, as you can not directly utilize image edit features such as file resize and file cropping.
  5. There will be more load on the database.
  6. Web server bandwidth will increase which adds additional costs.

Prerequisites

Following are some prerequisites before you proceed any further in this tutorial:

  1. Knowledge of ASP.NET MVC5.
  2. Knowledge of HTML.
  3. Knowledge of Bootstrap.
  4. Knowledge of C# Programming.

You can download the complete source code for this tutorial or you can follow the step by step discussion below. The sample code is being developed in Microsoft Visual Studio 2015 Enterprise.

Let's begin now.

Step 1

First, create your SQL server database and name it "db_img". Then execute following script into your SQL server database i.e.

  1. USE [db_img]  
  2. GO  
  3. /****** Object:  StoredProcedure [dbo].[sp_insert_file]    Script Date: 11/18/2018 12:27:55 AM ******/  
  4. DROP PROCEDURE [dbo].[sp_insert_file]  
  5. GO  
  6. /****** Object:  StoredProcedure [dbo].[sp_get_file_details]    Script Date: 11/18/2018 12:27:55 AM ******/  
  7. DROP PROCEDURE [dbo].[sp_get_file_details]  
  8. GO  
  9. /****** Object:  StoredProcedure [dbo].[sp_get_all_files]    Script Date: 11/18/2018 12:27:55 AM ******/  
  10. DROP PROCEDURE [dbo].[sp_get_all_files]  
  11. GO  
  12. /****** Object:  Table [dbo].[tbl_file]    Script Date: 11/18/2018 12:27:55 AM ******/  
  13. DROP TABLE [dbo].[tbl_file]  
  14. GO  
  15. /****** Object:  Table [dbo].[tbl_file]    Script Date: 11/18/2018 12:27:55 AM ******/  
  16. SET ANSI_NULLS ON  
  17. GO  
  18. SET QUOTED_IDENTIFIER ON  
  19. GO  
  20. CREATE TABLE [dbo].[tbl_file](  
  21.  [file_id] [int] IDENTITY(1,1) NOT NULL,  
  22.  [file_name] [nvarchar](maxNOT NULL,  
  23.  [file_ext] [nvarchar](maxNOT NULL,  
  24.  [file_base6] [nvarchar](maxNOT NULL,  
  25.  CONSTRAINT [PK_tbl_file] PRIMARY KEY CLUSTERED   
  26. (  
  27.  [file_id] ASC  
  28. )WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ONON [PRIMARY]  
  29. ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]  
  30.   
  31. GO  
  32. /****** Object:  StoredProcedure [dbo].[sp_get_all_files]    Script Date: 11/18/2018 12:27:55 AM ******/  
  33. SET ANSI_NULLS ON  
  34. GO  
  35. SET QUOTED_IDENTIFIER ON  
  36. GO  
  37. -- =============================================  
  38. -- Author:  <Author,,Name>  
  39. -- Create date: <Create Date,,>  
  40. -- Description: <Description,,>  
  41. -- =============================================  
  42. CREATE PROCEDURE [dbo].[sp_get_all_files]  
  43.    
  44. AS  
  45. BEGIN  
  46. /****** Script for SelectTopNRows command from SSMS  ******/  
  47.  SELECT [file_id]  
  48.     ,[file_name]  
  49.     ,[file_ext]  
  50.  FROM [db_img].[dbo].[tbl_file]  
  51. END  
  52.   
  53. GO  
  54. /****** Object:  StoredProcedure [dbo].[sp_get_file_details]    Script Date: 11/18/2018 12:27:55 AM ******/  
  55. SET ANSI_NULLS ON  
  56. GO  
  57. SET QUOTED_IDENTIFIER ON  
  58. GO  
  59. -- =============================================  
  60. -- Author:  <Author,,Name>  
  61. -- Create date: <Create Date,,>  
  62. -- Description: <Description,,>  
  63. -- =============================================  
  64. CREATE PROCEDURE [dbo].[sp_get_file_details]   
  65.  @file_id INT  
  66. AS  
  67. BEGIN  
  68. /****** Script for SelectTopNRows command from SSMS  ******/  
  69.  SELECT [file_id]  
  70.     ,[file_name]  
  71.     ,[file_ext]  
  72.     ,[file_base6]  
  73.  FROM [db_img].[dbo].[tbl_file]  
  74.  WHERE [tbl_file].[file_id] = @file_id  
  75. END  
  76.   
  77. GO  
  78. /****** Object:  StoredProcedure [dbo].[sp_insert_file]    Script Date: 11/18/2018 12:27:55 AM ******/  
  79. SET ANSI_NULLS ON  
  80. GO  
  81. SET QUOTED_IDENTIFIER ON  
  82. GO  
  83. -- =============================================  
  84. -- Author:  <Author,,Name>  
  85. -- Create date: <Create Date,,>  
  86. -- Description: <Description,,>  
  87. -- =============================================  
  88. CREATE PROCEDURE [dbo].[sp_insert_file]  
  89.  @file_name NVARCHAR(MAX),  
  90.  @file_ext NVARCHAR(MAX),  
  91.  @file_base64 NVARCHAR(MAX)  
  92. AS  
  93. BEGIN  
  94. /****** Script for SelectTopNRows command from SSMS  ******/  
  95.  INSERT INTO [dbo].[tbl_file]  
  96.            ([file_name]  
  97.            ,[file_ext]  
  98.            ,[file_base6])  
  99.      VALUES  
  100.            (@file_name  
  101.            ,@file_ext  
  102.            ,@file_base64)  
  103. END  
  104.   
  105. GO 

Step 2

Create a new MVC web project and name it "ImgSaveDb".

Step 3

Open the "Views->Shared->_Layout.cshtml" file and replace following code in it i.e.:

  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0">  
  6.     <title>@ViewBag.Title</title>  
  7.     @Styles.Render("~/Content/css")  
  8.     @Scripts.Render("~/bundles/modernizr")  
  9.   
  10.     <!-- Font Awesome -->  
  11.     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css" />  
  12.   
  13. </head>  
  14. <body>  
  15.     <div class="navbar navbar-inverse navbar-fixed-top">  
  16.         <div class="container">  
  17.             <div class="navbar-header">  
  18.                 <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">  
  19.                     <span class="icon-bar"></span>  
  20.                     <span class="icon-bar"></span>  
  21.                     <span class="icon-bar"></span>  
  22.                 </button>  
  23.             </div>  
  24.         </div>  
  25.     </div>  
  26.     <div class="container body-content">  
  27.         @RenderBody()  
  28.         <hr />  
  29.         <footer>  
  30.             <center>  
  31.                 <p><strong>Copyright © @DateTime.Now.Year - <a href="http://wwww.asmak9.com/">Asma's Blog</a>.</strong> All rights reserved.</p>  
  32.             </center>  
  33.         </footer>  
  34.     </div>  
  35.   
  36.     @*Scripts*@  
  37.     @Scripts.Render("~/bundles/jquery")  
  38.   
  39.     @Scripts.Render("~/bundles/jqueryval")  
  40.     @Scripts.Render("~/bundles/bootstrap")  
  41.   
  42.     @RenderSection("scripts", required: false)  
  43. </body>  
  44. </html> 

In the above code, I have simply created a basic default layout page and linked the required libraries into it.

Step 4

Create a new "Helper_Code\Objects\ImgObj.cs" file and replace the following code in it i.e.:

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="ImgObj.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace ImgSaveDb.Helper_Code.Objects  
  9. {  
  10.     using System;  
  11.     using System.Collections.Generic;  
  12.     using System.Linq;  
  13.     using System.Web;  
  14.   
  15.     /// <summary>  
  16.     /// Image object class.  
  17.     /// </summary>  
  18.     public class ImgObj  
  19.     {  
  20.         #region Properties  
  21.   
  22.         /// <summary>  
  23.         /// Gets or sets Image ID.  
  24.         /// </summary>  
  25.         public int FileId { getset; }  
  26.   
  27.         /// <summary>  
  28.         /// Gets or sets Image name.  
  29.         /// </summary>  
  30.         public string FileName { getset; }  
  31.   
  32.         /// <summary>  
  33.         /// Gets or sets Image extension.  
  34.         /// </summary>  
  35.         public string FileContentType { getset; }  
  36.  
  37.         #endregion  
  38.     }  

In the above code, I have simply created an object class which will map my image file metadata from SQL database.

Step 5

Now, create a new "Models\ImgViewModel.cs" file and replace the following code in it i.e.:

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="ImgViewModel.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace ImgSaveDb.Models  
  9. {  
  10.     using System.Collections.Generic;  
  11.     using System.ComponentModel.DataAnnotations;  
  12.     using System.Web;  
  13.     using Helper_Code.Objects;  
  14.   
  15.     /// <summary>  
  16.     /// Image view model class.  
  17.     /// </summary>  
  18.     public class ImgViewModel  
  19.     {  
  20.         #region Properties  
  21.   
  22.         /// <summary>  
  23.         /// Gets or sets Image file.  
  24.         /// </summary>  
  25.         [Required]  
  26.         [Display(Name = "Upload File")]  
  27.         public HttpPostedFileBase FileAttach { getset; }  
  28.   
  29.         /// <summary>  
  30.         /// Gets or sets Image file list.  
  31.         /// </summary>  
  32.         public List<ImgObj> ImgLst { getset; }  
  33.  
  34.         #endregion  
  35.     }  

In the above code, I have created my view model which I will attach with my view. Here, I have created a HttpPostedFileBase type file attachment property which will capture uploaded image/file data from the end-user and image object type list property which will display a list of images that I have stored in my database.

Step 6

Create a new "Controllers\ImgController.cs" file and replace the following code in it i.e.

  1. //-----------------------------------------------------------------------  
  2. // <copyright file="ImgController.cs" company="None">  
  3. //     Copyright (c) Allow to distribute this code and utilize this code for personal or commercial purpose.  
  4. // </copyright>  
  5. // <author>Asma Khalid</author>  
  6. //-----------------------------------------------------------------------  
  7.   
  8. namespace ImgSaveDb.Controllers  
  9. {  
  10.     using System;  
  11.     using System.Collections.Generic;  
  12.     using System.Linq;  
  13.     using System.Web;  
  14.     using System.Web.Mvc;  
  15.     using Helper_Code.Objects;  
  16.     using Models;  
  17.   
  18.     /// <summary>  
  19.     /// Image controller class.  
  20.     /// </summary>  
  21.     public class ImgController : Controller  
  22.     {  
  23.         #region Private Properties  
  24.   
  25.         /// <summary>  
  26.         /// Gets or sets database manager property.  
  27.         /// </summary>  
  28.         private db_imgEntities databaseManager = new db_imgEntities();  
  29.  
  30.         #endregion  
  31.  
  32.         #region Index view method.  
  33.  
  34.         #region Get: /Img/Index method.  
  35.   
  36.         /// <summary>  
  37.         /// Get: /Img/Index method.  
  38.         /// </summary>          
  39.         /// <returns>Return index view</returns>  
  40.         public ActionResult Index()  
  41.         {  
  42.             // Initialization.  
  43.             ImgViewModel model = new ImgViewModel { FileAttach = null, ImgLst = new List<ImgObj>() };  
  44.   
  45.             try  
  46.             {  
  47.                 // Settings.  
  48.                 model.ImgLst = this.databaseManager.sp_get_all_files().Select(p => new ImgObj  
  49.                                {  
  50.                                   FileId = p.file_id,  
  51.                                   FileName = p.file_name,  
  52.                                   FileContentType = p.file_ext  
  53.                                }).ToList();  
  54.             }  
  55.             catch (Exception ex)  
  56.             {  
  57.                 // Info  
  58.                 Console.Write(ex);  
  59.             }  
  60.   
  61.             // Info.  
  62.             return this.View(model);  
  63.         }  
  64.  
  65.         #endregion  
  66.  
  67.         #region POST: /Img/Index  
  68.   
  69.         /// <summary>  
  70.         /// POST: /Img/Index  
  71.         /// </summary>  
  72.         /// <param name="model">Model parameter</param>  
  73.         /// <returns>Return - Response information</returns>  
  74.         [HttpPost]  
  75.         [AllowAnonymous]  
  76.         [ValidateAntiForgeryToken]  
  77.         public ActionResult Index(ImgViewModel model)  
  78.         {  
  79.             // Initialization.  
  80.             string fileContent = string.Empty;  
  81.             string fileContentType = string.Empty;  
  82.   
  83.             try  
  84.             {  
  85.                 // Verification  
  86.                 if (ModelState.IsValid)  
  87.                 {  
  88.                     // Converting to bytes.  
  89.                     byte[] uploadedFile = new byte[model.FileAttach.InputStream.Length];  
  90.                     model.FileAttach.InputStream.Read(uploadedFile, 0, uploadedFile.Length);  
  91.   
  92.                     // Initialization.  
  93.                     fileContent = Convert.ToBase64String(uploadedFile);  
  94.                     fileContentType = model.FileAttach.ContentType;  
  95.   
  96.                     // Saving info.  
  97.                     this.databaseManager.sp_insert_file(model.FileAttach.FileName, fileContentType, fileContent);  
  98.                 }  
  99.   
  100.                 // Settings.  
  101.                 model.ImgLst = this.databaseManager.sp_get_all_files().Select(p => new ImgObj  
  102.                 {  
  103.                     FileId = p.file_id,  
  104.                     FileName = p.file_name,  
  105.                     FileContentType = p.file_ext  
  106.                 }).ToList();  
  107.             }  
  108.             catch (Exception ex)  
  109.             {  
  110.                 // Info  
  111.                 Console.Write(ex);  
  112.             }  
  113.   
  114.             // Info  
  115.             return this.View(model);  
  116.         }  
  117.  
  118.         #endregion  
  119.  
  120.         #endregion  
  121.  
  122.         #region Download file methods  
  123.  
  124.         #region GET: /Img/DownloadFile  
  125.   
  126.         /// <summary>  
  127.         /// GET: /Img/DownloadFile  
  128.         /// </summary>  
  129.         /// <param name="fileId">File Id parameter</param>  
  130.         /// <returns>Return download file</returns>  
  131.         public ActionResult DownloadFile(int fileId)  
  132.         {  
  133.             // Model binding.  
  134.             ImgViewModel model = new ImgViewModel { FileAttach = null, ImgLst = new List<ImgObj>() };  
  135.   
  136.             try  
  137.             {  
  138.                 // Loading dile info.  
  139.                 var fileInfo = this.databaseManager.sp_get_file_details(fileId).First();  
  140.   
  141.                 // Info.  
  142.                 return this.GetFile(fileInfo.file_base6, fileInfo.file_ext);  
  143.             }  
  144.             catch (Exception ex)  
  145.             {  
  146.                 // Info  
  147.                 Console.Write(ex);  
  148.             }  
  149.   
  150.             // Info.  
  151.             return this.View(model);  
  152.         }  
  153.  
  154.         #endregion  
  155.  
  156.         #endregion  
  157.  
  158.         #region Helpers  
  159.  
  160.         #region Get file method.  
  161.   
  162.         /// <summary>  
  163.         /// Get file method.  
  164.         /// </summary>  
  165.         /// <param name="fileContent">File content parameter.</param>  
  166.         /// <param name="fileContentType">File content type parameter</param>  
  167.         /// <returns>Returns - File.</returns>  
  168.         private FileResult GetFile(string fileContent, string fileContentType)  
  169.         {  
  170.             // Initialization.  
  171.             FileResult file = null;  
  172.   
  173.             try  
  174.             {  
  175.                 // Get file.  
  176.                 byte[] byteContent = Convert.FromBase64String(fileContent);  
  177.                 file = this.File(byteContent, fileContentType);  
  178.             }  
  179.             catch (Exception ex)  
  180.             {  
  181.                 // Info.  
  182.                 throw ex;  
  183.             }  
  184.   
  185.             // info.  
  186.             return file;  
  187.         }  
  188.  
  189.         #endregion  
  190.  
  191.         #endregion  
  192.     }  

In the above code, I have created a databaseManager private property which will allow me to access my SQL database via entity framework. Then, I have created "GetFile(...)" helper method which will convert my SQL database stored image file from base64 data format to byte data format. Then, I have created "DownloadFile(...)" method which will return image file stored in the SQL database base on the provided image file ID. Then, I have created GET "Index(...)" method which will retrieve the list of images data from SQL database and send it to the view page. Finally, I have created POST() "Index(...)" method which will receive the input image file from the end-user, then convert that file into a base64 data format and finally save the base64 data format file into the SQL database.

Step 7

Now, create a view "Views\Img\Index.cshtml" file and replace the following code in it i.e.

  1. @using ImgSaveDb.Models  
  2.   
  3. @model ImgSaveDb.Models.ImgViewModel  
  4.   
  5. @{  
  6.     ViewBag.Title = "ASP.NET MVC5: Upload Image into Database";  
  7. }  
  8.   
  9.   
  10. <div class="row">  
  11.     <div class="panel-heading">  
  12.         <div class="col-md-8">  
  13.             <h3>  
  14.                 <i class="fa fa-file-text-o"></i>  
  15.                 <span>ASP.NET MVC5: Upload Image into Database</span>  
  16.             </h3>  
  17.         </div>  
  18.     </div>  
  19. </div>  
  20.   
  21. <br/>  
  22.   
  23. <div class="row">  
  24.     <div class="col-md-6 col-md-push-2">  
  25.         <section>  
  26.             @using (Html.BeginForm("Index", "Img", FormMethod.Post, new { enctype = "multipart/form-data", @class = "form-horizontal"role = "form" }))  
  27.             {  
  28.                 @Html.AntiForgeryToken()  
  29.   
  30.                 <div class="well bs-component">  
  31.                     <br />  
  32.   
  33.                     <div class="row">  
  34.                         <div class="col-md-12">  
  35.                             <div class="col-md-8 col-md-push-2">  
  36.                                 <div class="input-group">  
  37.                                     <span class="input-group-btn">  
  38.                                         <span class="btn btn-default btn-file">  
  39.                                             Browse…  
  40.                                             @Html.TextBoxFor(m => m.FileAttach, new { type = "file"placeholder = Html.DisplayNameFor(m => m.FileAttach), @class = "form-control" })  
  41.                                         </span>  
  42.                                     </span>  
  43.                                     <input type="text" class="form-control" readonly>  
  44.                                 </div>  
  45.                                 @Html.ValidationMessageFor(m => m.FileAttach, "", new { @class = "text-danger custom-danger" })  
  46.                             </div>  
  47.                         </div>  
  48.                     </div>  
  49.   
  50.                     <div class="form-group">  
  51.                         <div class="col-md-12">  
  52.                         </div>  
  53.                     </div>  
  54.   
  55.                     <div class="form-group">  
  56.                         <div class="col-md-offset-5 col-md-10">  
  57.                             <input type="submit" class="btn btn-danger" value="Upload" />  
  58.                         </div>  
  59.                     </div>  
  60.                 </div>  
  61.             }  
  62.         </section>  
  63.     </div>  
  64. </div>  
  65.   
  66. <hr />  
  67.   
  68. <div class="row">  
  69.     <div class="col-md-offset-4 col-md-8">  
  70.         <h3>List of Imagess </h3>  
  71.     </div>  
  72. </div>  
  73.   
  74. <hr />  
  75.   
  76. @if (Model.ImgLst != null &&  
  77.      Model.ImgLst.Count > 0)  
  78. {  
  79.     <div class="row">  
  80.         <div class="col-md-offset-1 col-md-8">  
  81.             <section>  
  82.                 <table class="table table-bordered table-striped">  
  83.                     <thead>  
  84.                         <tr>  
  85.                             <th style="text-align: center;">Sr.</th>  
  86.                             <th style="text-align: center;">Image Name</th>  
  87.                             <th style="text-align: center;"></th>  
  88.                         </tr>  
  89.                     </thead>  
  90.   
  91.                     <tbody>  
  92.                         @for (int i = 0; i < Model.ImgLst.Count; i++)  
  93.                         {  
  94.                             <tr>  
  95.                                 <td style="text-align: center;">@(i + 1)</td>  
  96.   
  97.                                 <td style="text-align: center;">  
  98.                                     <div class="input-group" style="height:40px;">  
  99.                                         <i class="fa fa-2x fa-paperclip text-navy"></i>  
  100.                                         <a class="download-file1" href="@Url.Action("DownloadFile", "Img", new { fileId = @Model.ImgLst[i].FileId })" target="_blank">  
  101.                                             @Model.ImgLst[i].FileName  
  102.                                         </a>  
  103.                                     </div>  
  104.                                 </td>  
  105.   
  106.                                 <td style="text-align: center;">  
  107.                                     <div>  
  108.                                         <img src="@Url.Action("DownloadFile", "Img", new { fileId = @Model.ImgLst[i].FileId })" width="100" height="100" />  
  109.                                     </div>  
  110.                                 </td>  
  111.                             </tr>  
  112.                         }  
  113.                     </tbody>  
  114.                 </table>  
  115.             </section>  
  116.         </div>  
  117.     </div>  
  118. }  
  119.   
  120. @section Scripts  
  121. {  
  122.     @*Scripts*@  
  123.     @Scripts.Render("~/bundles/bootstrap-file")  
  124.   
  125.     @*Styles*@  
  126.     @Styles.Render("~/Content/Bootstrap-file/css")  

In the above code, I have created a simple view for uploading an image file to the server for storing it into the SQL database and then display the uploaded image files list. I have created bootstrap style file upload control and a table to display the list of uploaded images on the server in the SQL database.

Step 8

Now, execute the project and you will be able to see the following in action i.e.:

ASP.NET MVC 5 - Upload Image/File Into Database

ASP.NET MVC 5 - Upload Image/File Into Database

ASP.NET MVC 5 - Upload Image/File Into Database

Conclusion

In this article, you learned about uploading of the image file into the database on ASP.NET MVC5 platform. You also learned how to convert the image file into the base64 data format. You also learned to convert base64 data format to byte data format. You also learned to retrieve image data stored in SQL server database as base64 and you learned about the advantages & disadvantages of storing image/file into the database.