using System; using System.Collections.Generic; using System.IO; using System.Net; using System.Threading.Tasks; using Core; using LiMan.APi.Data; using LiMan.DB.DBModels; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; namespace LiMan.APi.Controllers { /// /// Controller caricamento file /// [ApiController] [Route("api/filesave")] public class FilesaveController : ControllerBase { private readonly IWebHostEnvironment env; private readonly ILogger logger; private static IConfiguration _configuration; /// /// Dataservice x accesso DB /// protected ApiDataService dataService { get; set; } /// /// Init generico /// /// /// /// /// public FilesaveController(IConfiguration configuration, ApiDataService DataService, IWebHostEnvironment env, ILogger logger) { dataService = DataService; _configuration = configuration; this.env = env; this.logger = logger; logger.LogInformation("Avviata classe FilesaveController"); } /// /// Caricamento file effettivo via POST /// /// TicketId x riferimento /// Elenco files da caricare /// [HttpPost("single")] public async Task> PostSingleFile([FromForm] int ticketId, [FromForm] IFormFile file) { // max 200 mb long maxFileSize = 1024 * 1024 * 200; string ticketDir = $"T{ticketId:000000000}"; var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/api/filesave/list/{ticketId}"); List uploadResults = new(); string fileDir = env.ContentRootPath; string relDir = env.EnvironmentName; var uploadResult = new UploadResult(); string trustedFileNameForFileStorage; var untrustedFileName = file.FileName; uploadResult.FileName = untrustedFileName; var trustedFileNameForDisplay = WebUtility.HtmlEncode(untrustedFileName); if (file.Length == 0) { logger.LogInformation("{FileName} length is 0 (Err: 1)", trustedFileNameForDisplay); uploadResult.ErrorCode = 1; } else if (file.Length > maxFileSize) { logger.LogInformation("{FileName} of {Length} bytes is larger than the limit of {Limit} bytes (Err: 2)", trustedFileNameForDisplay, file.Length, maxFileSize); uploadResult.ErrorCode = 2; } else { try { DateTime oggi = DateTime.Today; trustedFileNameForFileStorage = Path.GetRandomFileName(); #if false relDir = Path.Combine(env.EnvironmentName, "unsafe_uploads", ticketDir); fileDir = Path.Combine(env.ContentRootPath, relDir); //string fileDir = Path.Combine(env.ContentRootPath, env.EnvironmentName, "unsafe_uploads", $"{oggi:yyyy}", $"{oggi:MM}", $"{oggi:dd}"); #endif relDir = _configuration["FileShare"]; fileDir = Path.Combine(relDir, ticketDir); if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } var path = Path.Combine(fileDir, trustedFileNameForFileStorage); await using FileStream fs = new(path, FileMode.Create); await file.CopyToAsync(fs); logger.LogInformation("{FileName} saved at {Path}", trustedFileNameForDisplay, path); uploadResult.Uploaded = true; uploadResult.StoredFileName = trustedFileNameForFileStorage; } catch (IOException ex) { logger.LogError("{FileName} error on upload (Err: 3): {Message}", trustedFileNameForDisplay, ex.Message); uploadResult.ErrorCode = 3; } } uploadResults.Add(uploadResult); // salvo su DB var fatto = dataService.FileAdd(ticketId, relDir, uploadResults); return new CreatedResult(resourcePath, uploadResult); } /// /// Caricamento file effettivo via POST /// /// TicketId x riferimento /// Elenco files da caricare /// [HttpPost()] public async Task>> PostFiles([FromForm] int ticketId, [FromForm] IEnumerable files) { // max 5 files var maxAllowedFiles = 10; // max 50 mb long maxFileSize = 1024 * 1024 * 50; var filesProcessed = 0; string ticketDir = $"T{ticketId:000000000}"; var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/api/filesave/list/{ticketId}"); List uploadResults = new(); string fileDir = env.ContentRootPath; string relDir = env.EnvironmentName; foreach (var file in files) { var uploadResult = new UploadResult(); string trustedFileNameForFileStorage; var untrustedFileName = file.FileName; uploadResult.FileName = untrustedFileName; var trustedFileNameForDisplay = WebUtility.HtmlEncode(untrustedFileName); if (filesProcessed < maxAllowedFiles) { if (file.Length == 0) { logger.LogInformation("{FileName} length is 0 (Err: 1)", trustedFileNameForDisplay); uploadResult.ErrorCode = 1; } else if (file.Length > maxFileSize) { logger.LogInformation("{FileName} of {Length} bytes is larger than the limit of {Limit} bytes (Err: 2)", trustedFileNameForDisplay, file.Length, maxFileSize); uploadResult.ErrorCode = 2; } else { try { DateTime oggi = DateTime.Today; trustedFileNameForFileStorage = Path.GetRandomFileName(); relDir = Path.Combine(env.EnvironmentName, "unsafe_uploads", ticketDir); fileDir = Path.Combine(env.ContentRootPath, relDir); //string fileDir = Path.Combine(env.ContentRootPath, env.EnvironmentName, "unsafe_uploads", $"{oggi:yyyy}", $"{oggi:MM}", $"{oggi:dd}"); if (!Directory.Exists(fileDir)) { Directory.CreateDirectory(fileDir); } var path = Path.Combine(fileDir, trustedFileNameForFileStorage); await using FileStream fs = new(path, FileMode.Create); await file.CopyToAsync(fs); logger.LogInformation("{FileName} saved at {Path}", trustedFileNameForDisplay, path); uploadResult.Uploaded = true; uploadResult.StoredFileName = trustedFileNameForFileStorage; } catch (IOException ex) { logger.LogError("{FileName} error on upload (Err: 3): {Message}", trustedFileNameForDisplay, ex.Message); uploadResult.ErrorCode = 3; } } filesProcessed++; } else { logger.LogInformation("{FileName} not uploaded because the request exceeded the allowed {Count} of files (Err: 4)", trustedFileNameForDisplay, maxAllowedFiles); uploadResult.ErrorCode = 4; } uploadResults.Add(uploadResult); } // salvo su DB var fatto = dataService.FileAdd(ticketId, relDir, uploadResults); return new CreatedResult(resourcePath, uploadResults); } /// /// Richiesta di registrazione ticket supporto /// /// Obj Richiesta // POST api/files/list/1 [HttpPost("list/{id}")] public async Task> list(int id, [FromBody] SupportRequest CurrRequest) { List result = new List(); // controllo valori if (CurrRequest.IsValid) { // cerco i files dato ticket result = await dataService.FileGetFilt(id); await dataService.recordCall(CurrRequest.CodInst, CurrRequest.CodApp, $"POST:api/files/list:{id}"); } return result; } } }