using AsbCloudApp.Data; using AsbCloudApp.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudWebApi.Controllers { [Route("api/files")] [ApiController] [Authorize] public class FileController : ControllerBase { private readonly IFileService fileService; private readonly IWellService wellService; public FileController(IFileService fileService, IWellService wellService) { this.fileService = fileService; this.wellService = wellService; } /// /// Сохраняет переданные файлы и информацию о них /// /// id скважины /// id категории файла /// id отправившего файл пользователя /// Коллекция файлов /// Токен отмены задачи /// [HttpPost] [Route("{idWell}/files")] [ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)] public async Task SaveFilesAsync(int idWell, int idCategory, int idUser, [FromForm] IFormFileCollection files, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var fileInfoCollection = files.Select(f => (f.FileName, idWell, idCategory, DateTime.Now, idUser)); var fileNamesAndIds = fileService.SaveFilesPropertiesToDb(idWell, idCategory, fileInfoCollection); foreach (var file in files) { var fileExtension = Path.GetExtension(file.FileName); var fileId = fileNamesAndIds[file.FileName]; var relativePath = Path.Combine(fileService.RootPath, $"{idWell}", $"{idCategory}", $"{fileId}" + $"{fileExtension}"); Directory.CreateDirectory(Path.GetDirectoryName(relativePath)); using var fileStream = new FileStream(relativePath, FileMode.Create); file.CopyTo(fileStream); } return Ok(); } /// /// Возвращает информацию о файлах для скважины в выбраной категории /// /// id скважины /// id категории файла /// дата начала /// дата окончания /// для пагинации кол-во записей пропустить /// для пагинации кол-во записей взять /// Токен отмены задачи /// Список информации о файлах в этой категории [HttpGet] [Route("{idWell}")] [ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)] public async Task GetFilesInfoAsync([FromRoute] int idWell, int skip = 0, int take = 32, int idCategory = default, DateTime begin = default, DateTime end = default, CancellationToken token = default) { int? idCompany = User.GetCompanyId(); if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var filesInfo = await fileService.GetFilesInfoAsync(idWell, idCategory, begin, end, skip, take, token).ConfigureAwait(false); if (filesInfo is null || !filesInfo.Items.Any()) return NoContent(); return Ok(filesInfo); } /// /// Возвращает файл с диска на сервере /// /// id скважины /// id запрашиваемого файла /// Токен отмены задачи /// Запрашиваемый файл [HttpGet] [Route("{idWell}/{fileId}")] [ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)] public async Task GetFileAsync([FromRoute] int idWell, int fileId, CancellationToken token = default) { try { int? idCompany = User.GetCompanyId(); if (idCompany is null) return Forbid(); if (!await wellService.IsCompanyInvolvedInWellAsync((int)idCompany, idWell, token).ConfigureAwait(false)) return Forbid(); var fileInfo = await fileService.GetFileInfoAsync(fileId, token); if (fileInfo is null) throw new FileNotFoundException(); // TODO: словарь content typoв var relativePath = Path.Combine(fileService.RootPath, $"{idWell}", $"{fileInfo.IdCategory}", $"{fileInfo.Id}" + Path.GetExtension($"{fileInfo.Name}")); return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Name); } catch (FileNotFoundException ex) { return NotFound($"Файл не найден. Текст ошибки: {ex.Message}"); } } } }