Upload Files to Azure Blob Storage Asp.net C#
Today, in this article, nosotros will discuss how to develop a web application to store uploaded files into the Azure Hulk Storage. Now, as we all know, Blob Storage is a role of the Azure Storage. And so, beginning, we will discuss some basic concepts nigh Azure Storage so, we will discuss how to store file data into the Azure Blob Storage. The Code example contains the both version of Asp.Net Core i.eastward. two.ane and 3.1.
Definition of Azure Storage
Microsoft provides different ways to shop data or data in Azure. We can use dissimilar database types like Azure SQL Server, Azure Creation DB, or Azure Table Storage. Also, we can use either Azure Queues or Event Hubs for storing and sending a message like an E-mail, SMS, etc. In the same way, we can employ either Azure Files or Azure Hulk Storage to store files in Azure. Normally Azure Storage contains four different data services. These four information services identify together as a group and are named Azure Storage. Azure storage consists of Azure Blobs, Azure Files, Azure Queues, and Azure Tables. These 4 data storage services are always bachelor in special consideration because they all are primitive and cloud-based storage services and can exist used together in the same application. The below paradigm shows all the elements of Azure Storage.
Storage Business relationship
In Azure, Storage Business relationship e'er acts as a container that consists of a multiple prepare of Azure Storage Service together. In Storage Account, merely data services from the Azure Storage grouping tin exist included similar Azure Blobs, Files, Queues, and Tables. So, basically, it acts equally a grouping which contains multiple data services of Azure Storage. The beneath image demonstrates the basic concept of Azure Storage Accounts.
Prerequisites
- Microsoft Visual Studio 2017
- Account in Azure Portal.
If yous don't have any existing Azure account, then you tin create a free trial account in the Azure portal using your email id.
Create an Azure Storage Account
To create the Azure Storage Account in Azure Portal, first, you lot demand to log in to the Azure Portal and and so perform the below steps.
Step ane
Click on the Azure Storage Accounts option from the Resources Dashboard.
On the Create Azure Storage Account, click on the Add together push on the Storage Business relationship folio.
Now, provide the related required information to create an Azure Storage account.
Step 4
In the higher up epitome, Storage Account Name means Account Name. Also, select Storage V2 options for availing the service of all four data services of Azure Storage Accounts.
Step 5
At present, click the "Review and Create" button.
Step vi
After the settings are validated, click "Create" to create the business relationship.
Footstep seven
The business relationship cosmos takes some fourth dimension. Wait for the portal to display the notification telling that the deployment succeeded and click the notification.
Step 8
Once the deployment is succeeded, click the "Get to resource" option to open Storage Business relationship.
Step 9
Once Storage Account is created, click on Admission Keys options of the left panel and copy the ConnectionString value. This value is needed to be provided in our web application so that nosotros can upload files in Azure Blob Storage.
Create a Spider web Application using ASP.NET Core in Visual Studio
Stride 1
Now, open up Microsoft Visual Studio 2017 and click on File --> New --> Projects.
Select the Web Awarding project template and click the OK button.
In the Project Template box, select Web Application (Model-View-Controller) options and click on the OK button.
Step 4
At present a blank project solution is ready.
Stride v
Offset, open the App.Config file and shop the connections string to this file which nosotros already copied from the Azure portal.
- {
- "Logging" : {
- "LogLevel" : {
- "Default" : "Warning"
- }
- },
- "AllowedHosts" : "*" ,
- "BlobConnections" : "" ,
- "ConnectionStrings" : {
- "AccessKey" : "DefaultEndpointsProtocol=https;AccountName=testblobdump;AccountKey=ADSSADS222SSDbfOcGSuHbKnTlExh3kieXy6zwMZ/F3vDnOGT1uV5oy1KEYZ3ui6WFhayHC5tLkCA==;EndpointSuffix=core.windows.net"
- }
- }
Stride half dozen
Now, add another Form Library Projection to create the Service Layer.
Step 7
Later adding the new projects, we need to install the below NuGet Packages to access the Azure Storage business relationship using Windows Azure Storage customer driver.
Now, add another class library project for Data Context and add together a form called Products and define the Product model class as beneath.
- using System;
- using System.Collections.Generic;
- using System.ComponentModel.DataAnnotations;
- using Organisation.ComponentModel.DataAnnotations.Schema;
- using Arrangement.Text;
- using Microsoft.AspNetCore.Http;
- namespace DataContext.Models
- {
- [Table("Product" , Schema = "Core" )]
- public class Product
- {
- public Product()
- {
- CreatedDate = DateTime.Now;
- }
- [Cardinal]
- public int ProductId { get ; set ; }
- [Required(ErrorMessage ="Please Enter Name" )]
- [Cavalcade(TypeName ="varchar(l)" )]
- public string Name { become ; prepare ; }
- public decimal UnitPrice { go ; gear up ; }
- [Required(ErrorMessage ="Please Enter Description" )]
- [Column(TypeName ="varchar(500)" )]
- public cord Description { get ; fix ; }
- [Column(TypeName ="varchar(fifty)" )]
- public string ImageName { get ; fix ; }
- [Column(TypeName ="varchar(250)" )]
- public string ImagePath { get ; prepare ; }
- public DateTime CreatedDate { get ; set ; }
- public DateTime? UpdatedDate { become ; prepare ; }
- [NotMapped]
- public IFormFile File { get ; set ; }
- }
- }
Pace ix
Now, select the Service Layer Projects and Create a New Binder chosen AppConfig.
Step 10
At present, within this folder, add a new class file chosen AppConfiguration.cs where we volition read the configuration file value past providing the primal as beneath.
- using Microsoft.Extensions.Configuration;
- using System;
- using System.Collections.Generic;
- using Organisation.IO;
- using System.Text;
- namespace ServiceLayer.AppConfig
- {
- public static course AppConfiguration
- {
- private static IConfiguration currentConfig;
- public static void SetConfig(IConfiguration configuration)
- {
- currentConfig = configuration;
- }
- public static string GetConfiguration( string configKey)
- {
- attempt
- {
- cord connectionString = currentConfig.GetConnectionString(configKey);
- render connectionString;
- }
- grab (Exception ex)
- {
- throw (ex);
- }
- return "" ;
- }
- }
- }
Step 11
Now, add another class called BlobStorageService.cs and add the below code. This service is basically responsible to shop the uploaded file byte contained in the Azure Blob Storage. When it volition upload the file in blob storage, it first creates a container called Upload and so within the container create a logical folder with the current date, then inside that logical binder original file will be stored. Simply in this example, we need to retrieve ane thing very clearly that in Azure Blob Storage, there is no option for creating a folder. We tin can carve up uploaded files logically in a date-wise, month-wise, or year wise subgrouping. This can be washed with the help of the file proper noun.
For example, suppose we provide a file proper noun like this,
- Cord filename = "01-Jan-2019/abcwelcome.pdf"
In this instance, when this particular file is uploaded in Azure Hulk Storage, and so Azure creates a logical group named "01-Jan-2019" then stores the file abcwelcome.pdf within that logical group. But, in normal view every bit from the Azure portal, it will display just like folder file structure the aforementioned as windows explorer.
BlobStorageService.cs
- using Microsoft.WindowsAzure.Storage;
- using Microsoft.WindowsAzure.Storage.Hulk;
- using ServiceLayer.AppConfig;
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Threading.Tasks;
- namespace ServiceLayer
- {
- public class BlobStorageService
- {
- string accessKey = string .Empty;
- public BlobStorageService()
- {
- this .accessKey = AppConfiguration.GetConfiguration( "AccessKey" );
- }
- public string UploadFileToBlob( string strFileName, byte [] fileData, string fileMimeType)
- {
- effort
- {
- var _task = Task.Run(() =>this .UploadFileToBlobAsync(strFileName, fileData, fileMimeType));
- _task.Look();
- string fileUrl = _task.Result;
- render fileUrl;
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- }
- public async void DeleteBlobData( string fileUrl)
- {
- Uri uriObj =new Uri(fileUrl);
- string BlobName = Path.GetFileName(uriObj.LocalPath);
- CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(accessKey);
- CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
- string strContainerName = "uploads" ;
- CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(strContainerName);
- string pathPrefix = DateTime.Now.ToUniversalTime().ToString( "yyyy-MM-dd" ) + "/" ;
- CloudBlobDirectory blobDirectory = cloudBlobContainer.GetDirectoryReference(pathPrefix);
- CloudBlockBlob blockBlob = blobDirectory.GetBlockBlobReference(BlobName);
- look blockBlob.DeleteAsync();
- }
- private string GenerateFileName( string fileName)
- {
- cord strFileName = string .Empty;
- string [] strName = fileName.Separate( '.' );
- strFileName = DateTime.Now.ToUniversalTime().ToString("yyyy-MM-dd" ) + "/" + DateTime.Now.ToUniversalTime().ToString( "yyyyMMdd\\THHmmssfff" ) + "." + strName[strName.Length - 1];
- render strFileName;
- }
- private async Job< string > UploadFileToBlobAsync( string strFileName, byte [] fileData, cord fileMimeType)
- {
- try
- {
- CloudStorageAccount cloudStorageAccount = CloudStorageAccount.Parse(accessKey);
- CloudBlobClient cloudBlobClient = cloudStorageAccount.CreateCloudBlobClient();
- cord strContainerName = "uploads" ;
- CloudBlobContainer cloudBlobContainer = cloudBlobClient.GetContainerReference(strContainerName);
- cord fileName = this .GenerateFileName(strFileName);
- if (await cloudBlobContainer.CreateIfNotExistsAsync())
- {
- await cloudBlobContainer.SetPermissionsAsync(new BlobContainerPermissions { PublicAccess = BlobContainerPublicAccessType.Blob });
- }
- if (fileName != zippo && fileData != null )
- {
- CloudBlockBlob cloudBlockBlob = cloudBlobContainer.GetBlockBlobReference(fileName);
- cloudBlockBlob.Properties.ContentType = fileMimeType;
- wait cloudBlockBlob.UploadFromByteArrayAsync(fileData, 0, fileData.Length);
- return cloudBlockBlob.Uri.AbsoluteUri;
- }
- return "" ;
- }
- catch (Exception ex)
- {
- throw (ex);
- }
- }
- }
- }
At present, go to the information context layer and create the data context layer for storing the file information in the SQL database using the Entity Framework concept.
IUnitOfWork.cs
- using DataContext;
- using DataContext.Abstractions;
- namespace DataContext
- {
- public interface IUnitOfWork
- {
- IProductRepository ProductRepo {get ; }
- int SaveChanges();
- }
- }
UnitOfWork.cs
- using DataContext.Abstractions;
- using DataContext.DataContext;
- using DataContext.Implementation;
- using Microsoft.EntityFrameworkCore;
- namespace DataContext
- {
- public class UnitOfWork : IUnitOfWork
- {
- private DbContext db;
- public UnitOfWork()
- {
- db =new EFDBContext();
- }
- private IProductRepository _ProductRepo;
- public IProductRepository ProductRepo
- {
- get
- {
- if (_ProductRepo == nix )
- _ProductRepo =new ProductRepository(db);
- return _ProductRepo;
- }
- }
- public int SaveChanges()
- {
- return db.SaveChanges();
- }
- }
- }
IRepository.cs
- using System.Collections.Generic;
- namespace DataContext.Abstractions
- {
- public interface IRepository<TEntity> where TEntity : class
- {
- void Add(TEntity model);
- IEnumerable<TEntity> GetAll();
- TEntity GetById(object Id);
- void Modify(TEntity model);
- void Delete(TEntity model);
- void DeleteById( object Id);
- }
- }
Repository.cs
- using DataContext.Abstractions;
- using Microsoft.EntityFrameworkCore;
- using System.Collections.Generic;
- using Organisation.Linq;
- namespace DataContext.Implementation
- {
- public class Repository<TEntity> : IRepository<TEntity> where TEntity : class
- {
- protected DbContext db { become ; set ; }
- public void Add together(TEntity model)
- {
- db.Fix<TEntity>().Add(model);
- }
- public void Delete(TEntity model)
- {
- db.Prepare<TEntity>().Remove(model);
- }
- public void DeleteById( object Id)
- {
- TEntity entity = db.Set<TEntity>().Detect(Id);
- this .Delete(entity);
- }
- public IEnumerable<TEntity> GetAll()
- {
- return db.Fix<TEntity>().ToList();
- }
- public TEntity GetById( object Id)
- {
- return db.Set<TEntity>().Find(Id);
- }
- public void Alter(TEntity model)
- {
- db.Entry<TEntity>(model).Land = EntityState.Modified;
- }
- }
- }
EFDataContext.cs
- using DataContext.Models;
- using Microsoft.EntityFrameworkCore;
- using System;
- using System.Collections.Generic;
- using Organization.Text;
- namespace DataContext.DataContext
- {
- public grade EFDBContext :DbContext
- {
- public EFDBContext()
- {
- }
- public EFDBContext(DbContextOptions<EFDBContext> options) : base (options)
- {
- }
- public DbSet<Product> Product { get ; set ; }
- protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
- {
- if (!optionsBuilder.IsConfigured)
- {
- optionsBuilder.UseSqlServer(@"data source=xxxx; initial itemize=ProjectDB;persist security info=True;user id=sa;countersign=xxxxxxx;" );
- }
- base .OnConfiguring(optionsBuilder);
- }
- }
- }
ProductRepository.cs
- using DataContext.Abstractions;
- using DataContext.DataContext;
- using DataContext.Models;
- using Microsoft.EntityFrameworkCore;
- namespace DataContext.Implementation
- {
- public form ProductRepository : Repository<Product>, IProductRepository
- {
- private EFDBContext context
- {
- get
- {
- return db as EFDBContext;
- }
- }
- public ProductRepository(DbContext db)
- {
- this .db = db;
- }
- }
- }
Footstep xiii
Now, go to the main projects; i.east., MVC Application projects.
Pace 14
Select the Controller folder and add a new MVC Controller Proper noun ProductsController.cs
Step 15
Now, within the controller class, write downwards the below code within the Index Method.
- public IActionResult Index()
- {
- return View(_context.ProductRepo.GetAll());
- }
Step xvi
At present, see a new view against the Index method by clicking the right mouse push. A new view has been added in the view folder. Now add the beneath code in the view file.
- @model DataContext.Models.Product
- @{
- ViewData["Title" ] = "Details" ;
- }
- <h2>Details</h2>
- <div>
- <h4>Product</h4>
- <hr />
- <dlclass = "dl-horizontal" >
- <dt>
- @Html.DisplayNameFor(model => model.Name)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.Proper name)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.UnitPrice)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.UnitPrice)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.Description)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.Description)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.ImageName)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.ImageName)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.ImagePath)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.ImagePath)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.CreatedDate)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.CreatedDate)
- </dd>
- <dt>
- @Html.DisplayNameFor(model => model.UpdatedDate)
- </dt>
- <dd>
- @Html.DisplayFor(model => model.UpdatedDate)
- </dd>
- </dl>
- </div>
- <div>
- <a asp-action="Edit" asp-road-id= "@Model.ProductId" >Edit</a> |
- <a asp-action="Alphabetize" >Back to Listing</a>
- </div>
Stride 17
Now, create a new method for creating in the ProductsController and add related view against that action method.
- public IActionResult Create()
- {
- render View();
- }
Create.cshtml
- @model DataContext.Models.Product
- @{
- ViewData["Title" ] = "Create" ;
- }
- <h2>Create</h2>
- <h4>Product</h4>
- <hr />
- @using (Html.BeginForm( "Create" , "Products" , FormMethod.Post, new { enctype = "multipart/form-data" }))
- {
- @Html.AntiForgeryToken()
- <divcourse = "form-horizontal" >
- @Html.ValidationSummary(true , "" , new { @ grade = "text-danger" })
- <divclass = "form-group" >
- @Html.LabelFor(model => model.Proper noun, htmlAttributes:new { @ grade = "control-characterization col-doc-two" })
- <divclass = "col-medico-ten" >
- @Html.EditorFor(model => model.Proper noun,new { htmlAttributes = new { @ form = "form-control" } })
- @Html.ValidationMessageFor(model => model.Proper name,"" , new { @ class = "text-danger" })
- </div>
- </div>
- <divclass = "grade-grouping" >
- @Html.LabelFor(model => model.Clarification, htmlAttributes:new { @ grade = "control-label col-doc-2" })
- <divclass = "col-doctor-10" >
- @Html.EditorFor(model => model.Description,new { htmlAttributes = new { @ class = "form-control" } })
- @Html.ValidationMessageFor(model => model.Description,"" , new { @ grade = "text-danger" })
- </div>
- </div>
- <divclass = "form-grouping" >
- @Html.LabelFor(model => model.UnitPrice, htmlAttributes:new { @ class = "command-label col-md-2" })
- <divcourse = "col-medico-x" >
- @Html.EditorFor(model => model.UnitPrice,new { htmlAttributes = new { @ class = "form-control" } })
- @Html.ValidationMessageFor(model => model.UnitPrice,"" , new { @ grade = "text-danger" })
- </div>
- </div>
- <divgrade = "form-group" >
- @Html.LabelFor(model => model.File, htmlAttributes:new { @ class = "control-label col-doctor-2" })
- <divgrade = "col-md-10" >
- @Html.TextBoxFor(yard => m.File,new { type = "file" })
- @Html.ValidationMessageFor(one thousand => m.File)
- </div>
- </div>
- <divcourse = "form-group" >
- <divcourse = "col-dr.-offset-2 col-md-10" >
- <input blazon="submit" value= "Create" grade = "btn btn-default" />
- </div>
- </div>
- </div>
- }
- <div>
- <a asp-activeness="Index" >Back to List</a>
- </div>
- @section Scripts {
- @{wait Html.RenderPartialAsync("_ValidationScriptsPartial" );}
- }
Step 18
Now, create an action method for saving the data and write downwardly the beneath code.
- [HttpPost]
- [ValidateAntiForgeryToken]
- public IActionResult Create(Product production)
- {
- if (ModelState.IsValid)
- {
- #region Read File Content
- var uploads = Path.Combine(env.WebRootPath,"uploads" );
- bool exists = Directory.Exists(uploads);
- if (!exists)
- Directory.CreateDirectory(uploads);
- var fileName = Path.GetFileName(product.File.FileName);
- var fileStream =new FileStream(Path.Combine(uploads, production.File.FileName), FileMode.Create);
- string mimeType = product.File.ContentType;
- byte [] fileData = new byte [product.File.Length];
- BlobStorageService objBlobService =new BlobStorageService();
- production.ImagePath = objBlobService.UploadFileToBlob(product.File.FileName, fileData, mimeType);