From b80f6a9a6ae8466ea26e86c2ad464ecb2a425258 Mon Sep 17 00:00:00 2001
From: Lucca Santangelo <luccasant95@gmail.com>
Date: Fri, 6 Nov 2020 21:38:05 -0300
Subject: [PATCH] file upload

---
 .../Tsi1.Api/Controllers/CourseController.cs  |  9 ---
 .../Tsi1.Api/Controllers/FileController.cs    |  9 +--
 .../Tsi1.Api/Controllers/TenantController.cs  |  4 -
 Tsi1.Api/Tsi1.Api/Startup.cs                  |  3 +-
 .../HostedServices/FileCleanerService.cs      | 41 ++++++++++
 .../Interfaces/IFileService.cs                |  5 +-
 .../Services/FileService.cs                   | 78 +++++++------------
 7 files changed, 75 insertions(+), 74 deletions(-)
 create mode 100644 Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleanerService.cs

diff --git a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
index cb90fae..70011e2 100644
--- a/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
+++ b/Tsi1.Api/Tsi1.Api/Controllers/CourseController.cs
@@ -49,7 +49,6 @@ namespace Tsi1.Api.Controllers
         public async Task<IActionResult> Create(CourseCreateDto newCourse)
         {
             var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
-
             newCourse.TenantId = tenantId;
 
             var result = await _courseService.Create(newCourse);
@@ -58,10 +57,6 @@ namespace Tsi1.Api.Controllers
                 return BadRequest(result.Message);
             }
 
-            var path = Path.Combine(tenantId.ToString(), result.Data.Id.ToString());
-
-            _fileService.CreateFolder(path);
-
             return Ok();
         }
 
@@ -213,10 +208,6 @@ namespace Tsi1.Api.Controllers
                 return NotFound(result.Message);
             }
 
-            var path = Path.Combine(result.Data.TenantId.ToString(), result.Data.Id.ToString());
-
-            _fileService.DeleteFolder(path);
-
             return Ok();
         }
 
diff --git a/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs b/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs
index 144a829..fb7296d 100644
--- a/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs
+++ b/Tsi1.Api/Tsi1.Api/Controllers/FileController.cs
@@ -22,13 +22,12 @@ namespace Tsi1.Api.Controllers
         }
 
         [Authorize(Roles = UserTypes.Professor)]
-        [HttpPost("Create/{courseId}")]
-        public async Task<IActionResult> Create(IFormFile file, int courseId)
+        [HttpPost("Upload/{courseId}")]
+        public async Task<IActionResult> Upload(IFormFile file, int courseId)
         {
-            var tenantId = int.Parse(HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value);
-
-            var result = await _fileService.Create(file, tenantId, courseId);
+            var tenantId = HttpContext.User.Claims.FirstOrDefault(x => x.Type == "TenantId").Value;
 
+            var result = await _fileService.Create(file, tenantId, courseId.ToString());
             if (result.HasError)
             {
                 return BadRequest(result.Message);
diff --git a/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs b/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs
index 92a0665..9b59731 100644
--- a/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs
+++ b/Tsi1.Api/Tsi1.Api/Controllers/TenantController.cs
@@ -50,8 +50,6 @@ namespace Tsi1.Api.Controllers
                 return BadRequest(result.Message);
             }
 
-            _fileService.CreateFolder(result.Data.Id.ToString());
-
             return Ok(result.Data);
         }
 
@@ -90,8 +88,6 @@ namespace Tsi1.Api.Controllers
                 return NotFound(result.Message);
             }
 
-            _fileService.DeleteFolder(tenantId.ToString());
-
             return Ok();
         }
 
diff --git a/Tsi1.Api/Tsi1.Api/Startup.cs b/Tsi1.Api/Tsi1.Api/Startup.cs
index 71f448f..55f7de4 100644
--- a/Tsi1.Api/Tsi1.Api/Startup.cs
+++ b/Tsi1.Api/Tsi1.Api/Startup.cs
@@ -24,6 +24,7 @@ using Microsoft.OpenApi.Models;
 using Tsi1.Api.Infrastructure;
 using Tsi1.Api.SignalR;
 using Tsi1.BusinessLayer.Helpers;
+using Tsi1.BusinessLayer.HostedServices;
 using Tsi1.BusinessLayer.Interfaces;
 using Tsi1.BusinessLayer.Services;
 using Tsi1.DataLayer;
@@ -67,7 +68,7 @@ namespace Tsi1.Api
             services.AddSingleton<IJwtAuthManager, JwtAuthManager>();
             services.AddHostedService<JwtRefreshTokenCache>();
             services.AddHostedService<JwtVerificationCodeCache>();
-
+            services.AddHostedService<FileCleanerService>();
 
             services.AddSingleton<IMessageService, MessageService>();
 
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleanerService.cs b/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleanerService.cs
new file mode 100644
index 0000000..0a95d33
--- /dev/null
+++ b/Tsi1.Api/Tsi1.BusinessLayer/HostedServices/FileCleanerService.cs
@@ -0,0 +1,41 @@
+using Microsoft.Extensions.Hosting;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Tsi1.BusinessLayer.Interfaces;
+
+namespace Tsi1.BusinessLayer.HostedServices
+{
+    public class FileCleanerService : IHostedService, IDisposable
+    {
+        private Timer _timer;
+        private readonly IFileService _fileService;
+
+        public FileCleanerService(IFileService fileService)
+        {
+            _fileService = fileService;
+        }
+
+        public Task StartAsync(CancellationToken cancellationToken)
+        {
+            throw new NotImplementedException();
+        }
+
+        private void DoWork(object state)
+        {
+
+        }
+
+        public Task StopAsync(CancellationToken cancellationToken)
+        {
+            throw new NotImplementedException();
+        }
+
+        public void Dispose()
+        {
+            _timer?.Dispose();
+        }
+    }
+}
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs
index ced47ca..d5651e0 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Interfaces/IFileService.cs
@@ -10,9 +10,8 @@ namespace Tsi1.BusinessLayer.Interfaces
 {
     public interface IFileService
     {
-        Task<ServiceResult<FileDto>> Create(IFormFile file, int tenantId, int courseId);
-        void CreateFolder(string folderPath);
-        void DeleteFolder(string folderPath);
+        Task<ServiceResult<string>> Create(IFormFile file, string tenantId, string courseId);
+        ServiceResult<bool> DeleteFile(string filePath);
         bool ExistFile(string relativePath);
     }
 }
diff --git a/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs b/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs
index 937a334..6a2f588 100644
--- a/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs
+++ b/Tsi1.Api/Tsi1.BusinessLayer/Services/FileService.cs
@@ -5,6 +5,7 @@ using Microsoft.EntityFrameworkCore;
 using System;
 using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 using Tsi1.BusinessLayer.Dtos;
@@ -27,13 +28,12 @@ namespace Tsi1.BusinessLayer.Services
         {
             _context = context;
             _mapper = mapper;
-            _path = hostingEnvironment.ContentRootPath + "/StaticFiles";
+            _path = Path.Combine(hostingEnvironment.ContentRootPath, "StaticFiles");
         }
 
         public async Task<ServiceResult<string>> SaveFile(IFormFile file, string filePath)
         {
             var result = new ServiceResult<string>();
-
             var fileStream = new FileStream(filePath, FileMode.Create);
 
             try
@@ -54,57 +54,37 @@ namespace Tsi1.BusinessLayer.Services
             return result;
         }
 
-       
-
-        public async Task<ServiceResult<FileDto>> Create(IFormFile file, int tenantId, int courseId)
+        public async Task<ServiceResult<string>> Create(IFormFile file, string tenantId, string courseId)
         {
-            var result = new ServiceResult<FileDto>();
-
-            var tenant = await _context.Tenants
-                .FirstOrDefaultAsync(x => x.Id == tenantId);
+            var result = new ServiceResult<string>();
 
-            var course = await _context.Courses
-                .FirstOrDefaultAsync(x => x.Id == courseId);
+            var path = Path.Combine(_path, tenantId, courseId);
+            Directory.CreateDirectory(path);
 
-            var filePath = Path.Combine(_path, tenant.Name, course.Name, file.FileName);
+            var fileName = GenerateFileName(file);
+            var filePath = Path.Combine(path, fileName);
+            var fileStream = new FileStream(filePath, FileMode.Create);
 
-            var existingFile = await _context.Files.FirstOrDefaultAsync(x => x.Path == filePath);
-            if (existingFile != null)
+            try
             {
-                result.HasError = true;
-                result.Message = string.Format(ErrorMessages.DuplicateFile, filePath);
-                return result;
+                await file.CopyToAsync(fileStream);
             }
-
-            var newFile = new DataLayer.Entities.File
-            {
-                Name = file.FileName,
-                Path = filePath.Replace(_path, ""),
-            };
-
-            _context.Add(newFile);
-            await _context.SaveChangesAsync();
-
-            var resultSaveFile = await this.SaveFile(file, filePath);
-            if (resultSaveFile.HasError)
+            catch (Exception)
             {
                 result.HasError = true;
-                result.Message = resultSaveFile.Message;
-
-                _context.Remove(newFile);
-                await _context.SaveChangesAsync();
-
+                result.Message = string.Format(ErrorMessages.ErrorSavingFile, filePath);
                 return result;
             }
+            finally
+            {
+                fileStream.Close();
+            }
 
-            var fileDto = _mapper.Map<FileDto>(newFile);
-            result.Data = fileDto;
-
+            result.Data = filePath.Replace(_path, string.Empty);
             return result;
         }
 
-
-        public async Task<ServiceResult<bool>> DeleteFile(string filePath)
+        public ServiceResult<bool> DeleteFile(string filePath)
         {
             var result = new ServiceResult<bool>();
             
@@ -122,24 +102,18 @@ namespace Tsi1.BusinessLayer.Services
             return result;
         }
 
-        public void CreateFolder(string folderPath)
+        public bool ExistFile(string relativePath)
         {
-            var path = Path.Combine(_path, folderPath);
-
-            Directory.CreateDirectory(path);
+            var path = Path.Combine(_path, relativePath);
+            return System.IO.File.Exists(path);
         }
 
-        public void DeleteFolder(string folderPath)
+        private string GenerateFileName(IFormFile file)
         {
-            var path = Path.Combine(_path, folderPath);
-
-            Directory.Delete(path);
-        }
+            var ext = file.FileName.Split(".").Last();
+            var fileName = Guid.NewGuid().ToString();
 
-        public bool ExistFile(string relativePath)
-        {
-            var path = Path.Combine(_path, relativePath);
-            return System.IO.File.Exists(path);
+            return fileName + "." + ext;
         }
     }
 }
-- 
GitLab