using Microsoft.AspNetCore.Hosting; 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.Net; using System.Threading.Tasks; using wispro.sp.share; namespace wispro.sp.api.Controllers { [Route("api/[controller]/[action]")] [ApiController] public class AttachFilesController : ControllerBase { private readonly IWebHostEnvironment env; private readonly ILogger logger; public AttachFilesController(IWebHostEnvironment env, ILogger logger) { this.env = env; this.logger = logger; } [HttpPost] public async Task>> PostFile( [FromForm] IEnumerable files) { var maxAllowedFiles = 3; long maxFileSize = 1024 * 1024 * 15; var filesProcessed = 0; var resourcePath = new Uri($"{Request.Scheme}://{Request.Host}/"); List uploadResults = new(); 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 { trustedFileNameForFileStorage = Path.GetRandomFileName(); var path = Path.Combine(env.ContentRootPath, env.EnvironmentName, "unsafe_uploads", 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); } return new CreatedResult(resourcePath, uploadResults); } } }