Skip to content

Commit

Permalink
Added upload and download functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
mazumdes committed Dec 8, 2021
1 parent 088ff78 commit d07af5e
Show file tree
Hide file tree
Showing 14 changed files with 345 additions and 159 deletions.
95 changes: 71 additions & 24 deletions Library.Encyclopedia.API/Controllers/FilesController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
using Library.Encyclopedia.DataAccess;
using Library.Encyclopedia.DataAccess.DataAccess;
using Library.Encyclopedia.Entity.Interfaces;
using Library.Encyclopedia.Entity.Models;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading.Tasks;

namespace Library.Encyclopedia.API.Controllers
Expand All @@ -16,11 +19,13 @@ namespace Library.Encyclopedia.API.Controllers
public class FilesController : ControllerBase
{
private readonly ILogger<FilesController> _logger;
private readonly IFilesAdapter filesAdapter;
private readonly IFilesDataAccess filesDataAccess;

public FilesController(ILogger<FilesController> logger, IApplicationDbContext dbContext)
public FilesController(ILogger<FilesController> logger, IApplicationDbContext dbContext, IFilesAdapter filesAdapter)
{
_logger = logger;
this.filesAdapter = filesAdapter;
this.filesDataAccess = new FilesDataAccess(dbContext);
}

Expand All @@ -32,28 +37,70 @@ public FilesController(ILogger<FilesController> logger, IApplicationDbContext db
/// <param name="size"></param>
/// <param name="asc"></param>
/// <returns></returns>
//[HttpPost("{id}")]
//[ApiKey]
//public async Task<IActionResult> Get(Guid id, List<IFormFile> files)
//{
// try
// {
// ////var response = await filesDataAccess.AddFiles(id, files);

// //if (response == null)
// //{
// // return StatusCode(204);
// //}
// //else
// //{
// // return Ok(response);
// //}
// }
// catch (Exception ex)
// {
// _logger.LogError(ex, $"an error has occured {ex.Message}");
// throw;
// }
//}
[HttpPost("{id}")]
[ApiKey]
public async Task<IActionResult> Post(Guid id, List<IFormFile> files, [FromForm] Dictionary<string, string> descriptions)
{
try
{
// Store files at remote location
var responses = filesAdapter.UploadFiles(id, files);

List<Files> fileResponses = new List<Files>();

// filter out the failed uploads
for (int i = 0; i < responses.Count(); i++)
{
if (responses.ToList()[i])
{
string fileNameWithoutExt = Path.GetFileNameWithoutExtension(files[i].FileName);
fileResponses.Add(new Files
{
Id = Guid.NewGuid(),
MainId = id,
FileName = files[i].FileName,
FilePath = $@"/encyclopedia-media/{id}/{files[i].FileName}",
FileType = files[i].ContentType,
FileDescription = descriptions.ContainsKey(fileNameWithoutExt) ? descriptions[fileNameWithoutExt] : null
});
}
}

// Save to database
await filesDataAccess.AddFiles(fileResponses);

return Ok(fileResponses);
}
catch (Exception ex)
{
_logger.LogError(ex, $"an error has occured {ex.Message}");
throw;
}
}

/// <summary>
/// Upload Files
/// </summary>
/// <param name="query"></param>
/// <param name="offset"></param>
/// <param name="size"></param>
/// <param name="asc"></param>
/// <returns></returns>
[HttpGet("{id}")]
[ApiKey]
public async Task<IActionResult> Get(Guid id, string directory)
{
try
{
var files = await filesDataAccess.GetFiles(id);
var fileResponses = filesAdapter.DownloadFiles(files, directory);
return Ok(fileResponses);
}
catch (Exception ex)
{
_logger.LogError(ex, $"an error has occured {ex.Message}");
throw;
}
}
}
}
10 changes: 10 additions & 0 deletions Library.Encyclopedia.API/Startup.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using Library.Encyclopedia.DataAccess;
using Library.Encyclopedia.DataAccess.FileAccess;
using Library.Encyclopedia.Entity.Interfaces;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.SpaServices.AngularCli;
Expand Down Expand Up @@ -27,7 +29,15 @@ public void ConfigureServices(IServiceCollection services)
configuration.RootPath = "ClientApp/dist";
});

string url = Configuration.GetValue<string>("FTPSettings:url");
string userName = Configuration.GetValue<string>("FTPSettings:username");
string password = Configuration.GetValue<string>("FTPSettings:password");

services.AddScoped<IApplicationDbContext>(s => new ApplicationDbContext(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IFilesAdapter>(s =>
{
return new FTPAdapter(url, new System.Net.NetworkCredential(userName, password));
});
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
Expand Down
9 changes: 7 additions & 2 deletions Library.Encyclopedia.API/appsettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,12 @@
},
"AllowedHosts": "*",
"ConnectionStrings": {
"DefaultConnection": "Server=localhost\\SQLEXPRESS01;Database=Encyclopedia;Trusted_Connection=True;"
"DefaultConnection": "Server=localhost;Database=Encyclopedia;User=root;Password=root"
},
"ApiKey": "5929b003-8895-4fb3-bbb0-2eb101c48f66"
"ApiKey": "5929b003-8895-4fb3-bbb0-2eb101c48f66",
"FTPSettings": {
"url": "10.161.100.82",
"username": "mazus01",
"password": ""
}
}
4 changes: 3 additions & 1 deletion Library.Encyclopedia.DataAccess/ApplicationDbContext.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Library.Encyclopedia.Entity.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Threading.Tasks;

namespace Library.Encyclopedia.DataAccess
Expand All @@ -14,7 +15,8 @@ public ApplicationDbContext(string connectionString)

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer(connectionString);
var serverVersion = new MySqlServerVersion(new Version(8, 0, 18));
optionsBuilder.UseMySql(connectionString, serverVersion);
}

public DbSet<Main> Main { get; set; }
Expand Down
28 changes: 26 additions & 2 deletions Library.Encyclopedia.DataAccess/DataAccess/FilesDataAccess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Library.Encyclopedia.DataAccess.DataAccess
Expand All @@ -17,9 +16,34 @@ public FilesDataAccess(IApplicationDbContext dbcontext)
_dbcontext = dbcontext;
}

public async Task<IEnumerable<Files>> GetFiles(Guid id)
{
return await _dbcontext.Files.Where(s => s.MainId == id).ToListAsync();
}

public async Task AddFiles(IEnumerable<Files> files)
{
await _dbcontext.Files.AddRangeAsync(files);
var existingFiles = await _dbcontext.Files.Where(s => s.MainId == files.FirstOrDefault().MainId).ToListAsync();
List<Files> newFiles = new List<Files>();
List<Files> oldFiles = new List<Files>();

foreach (var file in files)
{
if (!existingFiles.Any(s => s.FileName == file.FileName))
newFiles.Add(file);
else
{
var oldFile = existingFiles.FirstOrDefault(s => s.FileName == file.FileName);
oldFile.FileName = file.FileName;
oldFile.FileDescription = file.FileDescription;
oldFile.FilePath = file.FilePath;
oldFile.FileType = file.FileType;
oldFiles.Add(oldFile);
}
}

await _dbcontext.Files.AddRangeAsync(newFiles);
_dbcontext.Files.UpdateRange(oldFiles);
await _dbcontext.SaveChanges();
}

Expand Down
69 changes: 69 additions & 0 deletions Library.Encyclopedia.DataAccess/FileAccess/FTPAdapter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Library.Encyclopedia.Entity.Interfaces;
using Library.Encyclopedia.Entity.Models;
using Microsoft.AspNetCore.Http;
using Renci.SshNet;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace Library.Encyclopedia.DataAccess.FileAccess
{
public class FTPAdapter : IFilesAdapter
{
private readonly string url;
private readonly NetworkCredential networkCredential;

public FTPAdapter(string url, NetworkCredential networkCredential)
{
this.url = url;
this.networkCredential = networkCredential;
}

public IEnumerable<bool> DownloadFiles(IEnumerable<Files> files, string directory)
{
List<bool> responses = new List<bool>();
var customUrl = $@"/home/{networkCredential.UserName}";

using (SftpClient client = new SftpClient(url, 22, networkCredential.UserName, networkCredential.Password))
{
client.Connect();
foreach (var file in files)
{
using (var stream = File.OpenWrite(Path.Combine(directory, file.FileName)))
{
client.DownloadFile(customUrl + file.FilePath, stream);
responses.Add(true);
}
}
}

return responses;
}

public IEnumerable<bool> UploadFiles(Guid id, List<IFormFile> files)
{
List<bool> responses = new List<bool>();
var customUrl = $@"/home/{networkCredential.UserName}/encyclopedia-media/{id}/";

using (SftpClient client = new SftpClient(url, 22, networkCredential.UserName, networkCredential.Password))
{
client.Connect();
if (!client.Exists(customUrl))
client.CreateDirectory(customUrl);

foreach (var file in files)
{
if (client.Exists(customUrl + file.FileName))
client.DeleteFile(customUrl + file.FileName);

client.UploadFile(file.OpenReadStream(), customUrl + file.FileName);
responses.Add(true);
}
}

return responses;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Http.Features" Version="5.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="5.0.12" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="5.0.12">
<PrivateAssets>all</PrivateAssets>
Expand All @@ -15,6 +16,8 @@
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="5.0.3" />
<PackageReference Include="SSH.NET" Version="2020.0.1" />
</ItemGroup>

<ItemGroup>
Expand Down
Loading

0 comments on commit d07af5e

Please sign in to comment.