using AsbCloudApp.Data; using AsbCloudApp.Repositories; using AsbCloudApp.Requests; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudApp.Services { /// <summary> /// Сервис доступа к файлам /// </summary> public class FileService { private readonly IFileRepository fileRepository; private readonly IFileStorageRepository fileStorageRepository; /// <summary> /// Сервис доступа к файлам /// </summary> /// <param name="fileRepository"></param> /// <param name="fileStorageRepository"></param> public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { this.fileRepository = fileRepository; this.fileStorageRepository = fileStorageRepository; } /// <summary> /// переместить файл /// </summary> /// <param name="idWell"></param> /// <param name="idUser"></param> /// <param name="idCategory"></param> /// <param name="destinationFileName"></param> /// <param name="srcFilePath"></param> /// <param name="token"></param> /// <returns></returns> public async Task<FileInfoDto?> MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFilePath, CancellationToken token = default) { destinationFileName = Path.GetFileName(destinationFileName); srcFilePath = Path.GetFullPath(srcFilePath); var fileSize = fileStorageRepository.GetFileLength(srcFilePath); //save info to db var dto = new FileInfoDto { IdWell = idWell, IdAuthor = idUser, IdCategory = idCategory, Name = destinationFileName, Size = fileSize }; var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId); fileStorageRepository.MoveFile(srcFilePath, filePath); return await GetOrDefaultAsync(fileId, token); } /// <summary> /// Сохранить файл /// </summary> /// <param name="idWell"></param> /// <param name="idUser"></param> /// <param name="idCategory"></param> /// <param name="fileFullName"></param> /// <param name="fileStream"></param> /// <param name="token"></param> /// <returns></returns> public async Task<FileInfoDto> SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { //save info to db var dto = new FileInfoDto { IdWell = idWell, IdAuthor = idUser, IdCategory = idCategory, Name = Path.GetFileName(fileFullName), Size = fileStream.Length }; var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); //save stream to disk string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId); await fileStorageRepository.SaveFileAsync(filePath, fileStream, token); return (await GetOrDefaultAsync(fileId, token))!; } /// <summary> /// удалить файл /// </summary> /// <param name="idFile"></param> /// <param name="token"></param> /// <returns></returns> public Task<int> DeleteAsync(int idFile, CancellationToken token) => DeleteAsync(new int[] { idFile }, token); /// <summary> /// удалить файлы /// </summary> /// <param name="ids"></param> /// <param name="token"></param> /// <returns></returns> public async Task<int> DeleteAsync(IEnumerable<int> ids, CancellationToken token) { if (ids is null || !ids.Any()) return 0; var files = await fileRepository.DeleteAsync(ids, token).ConfigureAwait(false); if (files is null || !files.Any()) return 0; var filesName = files.Select(x => GetUrl(x.IdWell, x.IdCategory, x.Id, Path.GetExtension(x.Name))); fileStorageRepository.DeleteFiles(filesName); return files.Any() ? 1 : 0; } /// <summary> /// получить путь для скачивания /// </summary> /// <param name="fileInfo"></param> /// <returns></returns> public string GetUrl(FileInfoDto fileInfo) => GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); /// <summary> /// получить путь для скачивания /// </summary> /// <param name="idWell"></param> /// <param name="idCategory"></param> /// <param name="idFile"></param> /// <param name="dotExtention"></param> /// <returns></returns> public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => fileStorageRepository.GetFilePath(idWell, idCategory, idFile, dotExtention); /// <summary> /// пометить метку файла как удаленную /// </summary> /// <param name="idMark"></param> /// <param name="token"></param> /// <returns></returns> public Task<int> MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); /// <summary> /// Инфо о файле /// </summary> /// <param name="idsFile"></param> /// <param name="token"></param> /// <returns></returns> public async Task<IEnumerable<FileInfoDto>> GetInfoByIdsAsync(IEnumerable<int> idsFile, CancellationToken token) { var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); return result; } /// <summary> /// Получить файлы определенной категории /// </summary> /// <param name="request"></param> /// <param name="token"></param> /// <returns></returns> public Task<IEnumerable<FileInfoDto>> GetInfosAsync(FileRequest request, CancellationToken token) => fileRepository.GetInfosAsync(request, token); /// <summary> /// Получить список файлов в контейнере /// </summary> /// <param name="request"></param> /// <param name="token"></param> /// <returns></returns> public Task<PaginationContainer<FileInfoDto>> GetInfosPaginatedAsync(FileRequest request, CancellationToken token) => fileRepository.GetInfosPaginatedAsync(request, token); /// <summary> /// Пометить файл как удаленный /// </summary> /// <param name="idFile"></param> /// <param name="token"></param> /// <returns></returns> public Task<int> MarkAsDeletedAsync(int idFile, CancellationToken token = default) => fileRepository.MarkAsDeletedAsync(idFile, token); /// <summary> /// добавить метку на файл /// </summary> /// <param name="fileMarkDto"></param> /// <param name="idUser"></param> /// <param name="token"></param> /// <returns></returns> public Task<int> CreateFileMarkAsync(FileMarkDto fileMarkDto, int idUser, CancellationToken token) => fileRepository.CreateFileMarkAsync(fileMarkDto, idUser, token); /// <summary> /// Получить запись по id /// </summary> /// <param name="id"></param> /// <param name="token"></param> /// <returns></returns> public Task<FileInfoDto?> GetOrDefaultAsync(int id, CancellationToken token) => fileRepository.GetOrDefaultAsync(id, token); /// <summary> /// получить инфо о файле по метке /// </summary> /// <param name="idMark"></param> /// <param name="token"></param> /// <returns></returns> public Task<FileInfoDto> GetByMarkId(int idMark, CancellationToken token) => fileRepository.GetByMarkId(idMark, token); /// <summary> /// получить инфо о файле по метке /// </summary> /// <param name="idsMarks"></param> /// <param name="token"></param> /// <returns></returns> public Task<int> MarkFileMarkAsDeletedAsync(IEnumerable<int> idsMarks, CancellationToken token) => fileRepository.MarkFileMarkAsDeletedAsync(idsMarks, token); /// <summary> /// Удаление всех файлов по скважине помеченных как удаленные /// </summary> /// <param name="idWell"></param> /// <param name="token"></param> /// <returns></returns> public async Task<int> DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token) { var files = await fileRepository.GetInfosAsync( new FileRequest { IdWell = idWell, IsDeleted = true }, token); var result = await DeleteAsync(files.Select(x => x.Id), token); return result; } /// <summary> /// Удаление всех файлов с диска о которых нет информации в базе /// </summary> /// <param name="idWell"></param> /// <param name="token"></param> public async Task<int> DeleteFilesNotExistStorage(int idWell, CancellationToken token) { var files = await fileRepository.GetInfosAsync( new FileRequest { IdWell = idWell }, token); var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotInList(idWell, files.Select(x => x.Id))); return result; } /// <summary> /// Вывод списка всех файлов из базы, для которых нет файла на диске /// </summary> /// <param name="idWell"></param> /// <param name="token"></param> /// <returns></returns> public async Task<IEnumerable<FileInfoDto>> GetListFilesNotDisc(int idWell, CancellationToken token) { var files = await fileRepository.GetInfosAsync( new FileRequest { IdWell = idWell }, token); var result = fileStorageRepository.GetListFilesNotDisc(files); return result; } /// <summary> /// Получить файловый поток по идентификатору файла /// </summary> /// <param name="fileInfo"></param> /// <returns></returns> public Stream GetFileStream(FileInfoDto fileInfo) { var relativePath = GetUrl(fileInfo); var fileStream = new FileStream(Path.GetFullPath(relativePath), FileMode.Open); return fileStream; } } }