using AsbCloudApp.Data; using AsbCloudApp.Exceptions; using AsbCloudApp.Services; using AsbCloudDb.Model; using AsbCloudInfrastructure.Repository; using Mapster; using Microsoft.EntityFrameworkCore; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; namespace AsbCloudInfrastructure.Services { public class FileService : IFileService { public string RootPath { get; private set; } private readonly IFileRepository fileRepository; public FileService(IFileRepository fileRepository) { RootPath = "files"; this.fileRepository = fileRepository; } public async Task MoveAsync(int idWell, int? idUser, int idCategory, string destinationFileName, string srcFilePath, CancellationToken token = default) { destinationFileName = Path.GetFileName(destinationFileName); srcFilePath = Path.GetFullPath(srcFilePath); if (!File.Exists(srcFilePath)) throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); var sysFileInfo = new System.IO.FileInfo(srcFilePath); //save info to db var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, destinationFileName, sysFileInfo.Length, token) .ConfigureAwait(false); string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); File.Move(srcFilePath, filePath); return await GetInfoAsync(fileId, token); } public async Task SaveAsync(int idWell, int? idUser, int idCategory, string fileFullName, Stream fileStream, CancellationToken token) { //save info to db var fileId = await fileRepository.AddAsync(idWell, idUser, idCategory, Path.GetFileName(fileFullName), fileStream?.Length ?? 0, token) .ConfigureAwait(false); //save stream to disk string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId); Directory.CreateDirectory(Path.GetDirectoryName(filePath)); using var newfileStream = new FileStream(filePath, FileMode.Create); await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); return await GetInfoAsync(fileId, token); } private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) { return Path.Combine(RootPath, $"{idWell}", $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } public async Task GetInfoAsync(int idFile, CancellationToken token) { var dto = await fileRepository.GetInfoAsync(idFile, token).ConfigureAwait(false); var ext = Path.GetExtension(dto.Name); var relativePath = GetUrl(dto.IdWell, dto.IdCategory, dto.Id, ext); var fullPath = Path.GetFullPath(relativePath); if (!File.Exists(fullPath)) { throw new FileNotFoundException("not found", relativePath); } return dto; } public Task DeleteAsync(int idFile, CancellationToken token) => DeleteAsync(new int[] { idFile }, token); public async Task DeleteAsync(IEnumerable 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; foreach (var file in files) { var fileName = GetUrl(file.IdWell, file.IdCategory, file.Id, Path.GetExtension(file.Name)); if (File.Exists(fileName)) File.Delete(fileName); } return files.Any() ? 1 : 0; } public async Task GetUrl(int idFile) { var fileInfo = await fileRepository.GetInfoAsync(idFile, CancellationToken.None).ConfigureAwait(false); return GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); } public string GetUrl(FileInfoDto fileInfo) => GetUrl(fileInfo.IdWell, fileInfo.IdCategory, fileInfo.Id, Path.GetExtension(fileInfo.Name)); public string GetUrl(int idWell, int idCategory, int idFile, string dotExtention) => Path.Combine(RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) => fileRepository.MarkFileMarkAsDeletedAsync(new int[] { idMark }, token); public async Task> GetInfoByIdsAsync(IEnumerable idsFile, CancellationToken token) { var result = await fileRepository.GetInfoByIdsAsync(idsFile, token).ConfigureAwait(false); foreach (var entity in result) { var ext = Path.GetExtension(entity.Name); var relativePath = GetUrl(entity.IdWell, entity.IdCategory, entity.Id, ext); var fullPath = Path.GetFullPath(relativePath); if (!File.Exists(fullPath)) { throw new FileNotFoundException("not found", relativePath); } } return result; } } }