Upload And Download Multiple Files Using Web API

Today, we are going to cover uploading & downloading multiple files using ASP.Net Core 5.0 web API by a simple process.
 
Note
Since I have the latest .Net 5.0 installed on my machine I used this. This same technique works in .Net Core 3.1 and .Net Core 2.1 as well.
 
Begin with creating an empty web API project in visual studio and for target framework choose .Net 5.0.
 
No external packages were used in this project.
 
Create a Services folder and inside that create one FileService class and IFileService Interface in it.
 
We have used three methods in this FileService.cs 
  • UploadFile
  • DownloadFile
  • SizeConverter 
Since we need a folder to store these uploading files, here we have added one more parameter to pass the folder name as a string where it will store all these files.
 
FileService.cs
  1. using Microsoft.AspNetCore.Hosting;  
  2. using Microsoft.AspNetCore.Http;  
  3. using System;  
  4. using System.Collections.Generic;  
  5. using System.IO;  
  6. using System.IO.Compression;  
  7. using System.Linq;  
  8. using System.Threading.Tasks;  
  9.   
  10. namespace UploadandDownloadFiles.Services  
  11. {  
  12.     public class FileService :IFileService  
  13.     {  
  14.         #region Property  
  15.         private IHostingEnvironment _hostingEnvironment;  
  16.         #endregion  
  17.  
  18.         #region Constructor  
  19.         public FileService(IHostingEnvironment hostingEnvironment)  
  20.         {  
  21.             _hostingEnvironment = hostingEnvironment;  
  22.         }  
  23.         #endregion  
  24.  
  25.         #region Upload File  
  26.         public void UploadFile(List<IFormFile> files, string subDirectory)  
  27.         {  
  28.             subDirectory = subDirectory ?? string.Empty;  
  29.             var target = Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory);  
  30.   
  31.             Directory.CreateDirectory(target);  
  32.   
  33.             files.ForEach(async file =>  
  34.             {  
  35.                 if (file.Length <= 0) return;  
  36.                 var filePath = Path.Combine(target, file.FileName);  
  37.                 using (var stream = new FileStream(filePath, FileMode.Create))  
  38.                 {  
  39.                     await file.CopyToAsync(stream);  
  40.                 }  
  41.             });  
  42.         }  
  43.         #endregion  
  44.  
  45.         #region Download File  
  46.         public (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory)  
  47.         {  
  48.             var zipName = $"archive-{DateTime.Now.ToString("yyyy_MM_dd-HH_mm_ss")}.zip";  
  49.   
  50.             var files = Directory.GetFiles(Path.Combine(_hostingEnvironment.ContentRootPath, subDirectory)).ToList();  
  51.   
  52.             using (var memoryStream = new MemoryStream())  
  53.             {  
  54.                 using (var archive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))  
  55.                 {  
  56.                     files.ForEach(file =>  
  57.                     {  
  58.                         var theFile = archive.CreateEntry(file);  
  59.                         using (var streamWriter = new StreamWriter(theFile.Open()))  
  60.                         {  
  61.                             streamWriter.Write(File.ReadAllText(file));  
  62.                         }  
  63.   
  64.                     });  
  65.                 }  
  66.   
  67.                 return ("application/zip", memoryStream.ToArray(), zipName);  
  68.             }  
  69.   
  70.         }  
  71.         #endregion  
  72.  
  73.         #region Size Converter  
  74.         public string SizeConverter(long bytes)  
  75.         {  
  76.             var fileSize = new decimal(bytes);  
  77.             var kilobyte = new decimal(1024);  
  78.             var megabyte = new decimal(1024 * 1024);  
  79.             var gigabyte = new decimal(1024 * 1024 * 1024);  
  80.   
  81.             switch (fileSize)  
  82.             {  
  83.                 case var _ when fileSize < kilobyte:  
  84.                     return $"Less then 1KB";  
  85.                 case var _ when fileSize < megabyte:  
  86.                     return $"{Math.Round(fileSize / kilobyte, 0, MidpointRounding.AwayFromZero):##,###.##}KB";  
  87.                 case var _ when fileSize < gigabyte:  
  88.                     return $"{Math.Round(fileSize / megabyte, 2, MidpointRounding.AwayFromZero):##,###.##}MB";  
  89.                 case var _ when fileSize >= gigabyte:  
  90.                     return $"{Math.Round(fileSize / gigabyte, 2, MidpointRounding.AwayFromZero):##,###.##}GB";  
  91.                 default:  
  92.                     return "n/a";  
  93.             }  
  94.         }  
  95.         #endregion  
  96.   
  97.     }  
  98. }  
SizeConverter function is used to get the actual size of our uploading files to the server.
 
IFileService.cs
  1. using Microsoft.AspNetCore.Http;  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Threading.Tasks;  
  6.   
  7. namespace UploadandDownloadFiles.Services  
  8. {  
  9.    public interface IFileService  
  10.     {  
  11.         void UploadFile(List<IFormFile> files, string subDirectory);  
  12.         (string fileType, byte[] archiveData, string archiveName) DownloadFiles(string subDirectory);  
  13.          string SizeConverter(long bytes);  
  14.     }  
  15. }  
Let's add this service dependency in a startup.cs file
 
Startup.cs
  1. using Microsoft.AspNetCore.Builder;  
  2. using Microsoft.AspNetCore.Hosting;  
  3. using Microsoft.AspNetCore.HttpsPolicy;  
  4. using Microsoft.AspNetCore.Mvc;  
  5. using Microsoft.Extensions.Configuration;  
  6. using Microsoft.Extensions.DependencyInjection;  
  7. using Microsoft.Extensions.Hosting;  
  8. using Microsoft.Extensions.Logging;  
  9. using Microsoft.OpenApi.Models;  
  10. using System;  
  11. using System.Collections.Generic;  
  12. using System.Linq;  
  13. using System.Threading.Tasks;  
  14. using UploadandDownloadFiles.Services;  
  15.   
  16. namespace UploadandDownloadFiles  
  17. {  
  18.     public class Startup  
  19.     {  
  20.         public Startup(IConfiguration configuration)  
  21.         {  
  22.             Configuration = configuration;  
  23.         }  
  24.   
  25.         public IConfiguration Configuration { get; }  
  26.   
  27.         // This method gets called by the runtime. Use this method to add services to the container.  
  28.         public void ConfigureServices(IServiceCollection services)  
  29.         {  
  30.   
  31.             services.AddControllers();  
  32.             services.AddSwaggerGen(c =>  
  33.             {  
  34.                 c.SwaggerDoc("v1"new OpenApiInfo { Title = "UploadandDownloadFiles", Version = "v1" });  
  35.             });  
  36.   
  37.             services.AddTransient<IFileService, FileService>();  
  38.         }  
  39.   
  40.         // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.  
  41.         public void Configure(IApplicationBuilder app, IWebHostEnvironment env)  
  42.         {  
  43.             if (env.IsDevelopment())  
  44.             {  
  45.                 app.UseDeveloperExceptionPage();  
  46.                 app.UseSwagger();  
  47.                 app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json""UploadandDownloadFiles v1"));  
  48.             }  
  49.   
  50.             app.UseHttpsRedirection();  
  51.   
  52.             app.UseRouting();  
  53.   
  54.             app.UseAuthorization();  
  55.   
  56.             app.UseEndpoints(endpoints =>  
  57.             {  
  58.                 endpoints.MapControllers();  
  59.             });  
  60.         }  
  61.     }  
  62. }  
Create a FileController & now inject this IFileService using Constructor injection inside this FileController.
 
FileController.cs
  1. using Microsoft.AspNetCore.Hosting;  
  2. using Microsoft.AspNetCore.Http;  
  3. using Microsoft.AspNetCore.Mvc;  
  4. using System;  
  5. using System.Collections.Generic;  
  6. using System.ComponentModel.DataAnnotations;  
  7. using System.IO;  
  8. using System.Linq;  
  9. using System.Threading.Tasks;  
  10. using UploadandDownloadFiles.Services;  
  11.   
  12. namespace UploadandDownloadFiles.Controllers  
  13. {  
  14.     [Route("api/[controller]")]  
  15.     [ApiController]  
  16.     public class FileController : ControllerBase  
  17.     {  
  18.         #region Property  
  19.         private readonly IFileService _fileService;  
  20.         #endregion  
  21.  
  22.         #region Constructor  
  23.         public FileController(IFileService fileService)  
  24.         {  
  25.             _fileService = fileService;  
  26.         }  
  27.         #endregion  
  28.  
  29.         #region Upload  
  30.         [HttpPost(nameof(Upload))]  
  31.         public IActionResult Upload([Required] List<IFormFile> formFiles, [Required] string subDirectory)  
  32.         {  
  33.             try  
  34.             {  
  35.                 _fileService.UploadFile(formFiles, subDirectory);  
  36.   
  37.                 return Ok(new { formFiles.Count, Size = _fileService.SizeConverter(formFiles.Sum(f => f.Length)) });  
  38.             }  
  39.             catch (Exception ex)  
  40.             {  
  41.                 return BadRequest(ex.Message);  
  42.             }  
  43.         }  
  44.         #endregion  
  45.  
  46.         #region Download File  
  47.         [HttpGet(nameof(Download))]  
  48.         public IActionResult Download([Required]string subDirectory)  
  49.         {  
  50.   
  51.             try  
  52.             {  
  53.                 var (fileType, archiveData, archiveName) = _fileService.DownloadFiles(subDirectory);  
  54.   
  55.                 return File(archiveData, fileType, archiveName);  
  56.             }  
  57.             catch (Exception ex)  
  58.             {  
  59.                 return BadRequest(ex.Message);  
  60.             }  
  61.   
  62.         }  
  63.         #endregion  
  64.     }  
  65. }  
We can test our API's in both swagger and postman.
 
Upload And Download Multiple Files Using Web API
 
Here we see our two API's which we have created to upload and download, so let's test each of these individually.
 
Upload And Download Multiple Files Using Web API 
 
 
Pass the folder name inside the subDirectory and add files below to save inside the server and under the folder name. In response we see the total count of our files and the actual size of our entire files.
 
Upload And Download Multiple Files Using Web API 
 
Now will check with Download API. Since we have multiple files inside of our folder it will download as a Zip file where we need to extract that to check the files.
 
Upload And Download Multiple Files Using Web API
 
Git Hub Repo - Download Source Code
 
If you found this article helpful, Please give it a Upload And Download Multiple Files Using Web API
 
.... keep learning !!!