diff --git a/AsbCloudApp/AsbCloudApp.csproj b/AsbCloudApp/AsbCloudApp.csproj index 64a7b66a..5c826cb1 100644 --- a/AsbCloudApp/AsbCloudApp.csproj +++ b/AsbCloudApp/AsbCloudApp.csproj @@ -13,4 +13,12 @@ + + + + + + + + diff --git a/AsbCloudApp/Services/IFileService.cs b/AsbCloudApp/Services/IFileService.cs index a83d6d5c..a87397f7 100644 --- a/AsbCloudApp/Services/IFileService.cs +++ b/AsbCloudApp/Services/IFileService.cs @@ -14,11 +14,6 @@ namespace AsbCloudApp.Services /// public interface IFileService { - /// - /// Директория хранения файлов - /// - string RootPath { get; } - /// /// Сохранить файл /// diff --git a/AsbCloudApp/Services/IFileStorageRepository.cs b/AsbCloudApp/Services/IFileStorageRepository.cs new file mode 100644 index 00000000..6659e976 --- /dev/null +++ b/AsbCloudApp/Services/IFileStorageRepository.cs @@ -0,0 +1,51 @@ +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudApp.Services +{ + /// + /// Репозиторий хранения фалов + /// + public interface IFileStorageRepository + { + /// + /// Директория хранения файлов + /// + string RootPath { get; } + + /// + /// Получение длинны фала и проверка его наличия, если отсутствует падает исключение + /// + /// + /// + long GetLengthFile(string srcFilePath); + + /// + /// Перемещение файла + /// + /// + /// + void MoveFile (string srcFilePath, string filePath); + + /// + /// Копирование файла + /// + /// + Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token); + + /// + /// Удаление файла + /// + /// + void DeleteFile(string fileName); + + /// + /// Проверка наличия файла + /// + /// + /// + /// + bool FileExists(string fullPath, string fileName); + } +} diff --git a/AsbCloudInfrastructure/DependencyInjection.cs b/AsbCloudInfrastructure/DependencyInjection.cs index f178b648..5c1bf56f 100644 --- a/AsbCloudInfrastructure/DependencyInjection.cs +++ b/AsbCloudInfrastructure/DependencyInjection.cs @@ -155,6 +155,7 @@ namespace AsbCloudInfrastructure .Include(c => c.Wells) .Include(c => c.Deposit))); // может быть включен в сервис ClusterService services.AddTransient(); + services.AddTransient(); // Subsystem service services.AddTransient, CrudCacheServiceBase>(); services.AddTransient(); diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs new file mode 100644 index 00000000..6cb38cfb --- /dev/null +++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs @@ -0,0 +1,59 @@ +using AsbCloudApp.Exceptions; +using AsbCloudApp.Services; +using System.IO; +using System.Threading; +using System.Threading.Tasks; + +namespace AsbCloudInfrastructure.Repository +{ + public class FileStorageRepository : IFileStorageRepository + { + public string RootPath { get; private set; } + + public FileStorageRepository() + { + RootPath = "files"; + } + + public async Task CopyFileAsync(string filePath, Stream fileStream, CancellationToken token) + { + CreateDirectory(filePath); + using var newfileStream = new FileStream(filePath, FileMode.Create); + await fileStream.CopyToAsync(newfileStream, token).ConfigureAwait(false); + } + + public void DeleteFile(string fileName) + { + if (File.Exists(fileName)) + File.Delete(fileName); + } + + public long GetLengthFile(string srcFilePath) + { + if (!File.Exists(srcFilePath)) + throw new ArgumentInvalidException($"file {srcFilePath} doesn't exist", nameof(srcFilePath)); + + var sysFileInfo = new FileInfo(srcFilePath); + return sysFileInfo.Length; + } + + public void MoveFile(string srcFilePath, string filePath) + { + CreateDirectory(filePath); + File.Move(srcFilePath, filePath); + } + + public bool FileExists(string fullPath, string fileName) + { + if (!File.Exists(fullPath)) + throw new FileNotFoundException("not found", fileName); + + return true; + } + + private void CreateDirectory(string filePath) + { + Directory.CreateDirectory(Path.GetDirectoryName(filePath)); + } + } +} diff --git a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs index 0e840524..2780e7b1 100644 --- a/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs +++ b/AsbCloudInfrastructure/Services/DrillingProgram/DrillingProgramService.cs @@ -481,7 +481,8 @@ namespace AsbCloudInfrastructure.Services.DrillingProgram .Options; using var context = new AsbCloudDbContext(contextOptions); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var files = state.Parts.Select(p => fileService.GetUrl(p.File)); DrillingProgramMaker.UniteExcelFiles(files, tempResultFilePath, state.Parts, well); await fileService.MoveAsync(idWell, null, idFileCategoryDrillingProgram, resultFileName, tempResultFilePath, token); diff --git a/AsbCloudInfrastructure/Services/FileService.cs b/AsbCloudInfrastructure/Services/FileService.cs index cdfed260..5cb60fcd 100644 --- a/AsbCloudInfrastructure/Services/FileService.cs +++ b/AsbCloudInfrastructure/Services/FileService.cs @@ -16,13 +16,13 @@ namespace AsbCloudInfrastructure.Services { public class FileService : IFileService { - public string RootPath { get; private set; } private readonly IFileRepository fileRepository; + private readonly IFileStorageRepository fileStorageRepository; - public FileService(IFileRepository fileRepository) + public FileService(IFileRepository fileRepository, IFileStorageRepository fileStorageRepository) { - RootPath = "files"; this.fileRepository = fileRepository; + this.fileStorageRepository = fileStorageRepository; } public async Task MoveAsync(int idWell, int? idUser, int idCategory, @@ -30,10 +30,7 @@ namespace AsbCloudInfrastructure.Services { 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); + var fileSize = fileStorageRepository.GetLengthFile(srcFilePath); //save info to db var dto = new FileInfoDto { @@ -41,14 +38,13 @@ namespace AsbCloudInfrastructure.Services IdAuthor = idUser, IdCategory = idCategory, Name = destinationFileName, - Size = sysFileInfo.Length + Size = fileSize }; var fileId = await fileRepository.InsertAsync(dto, token) .ConfigureAwait(false); string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId); - Directory.CreateDirectory(Path.GetDirectoryName(filePath)); - File.Move(srcFilePath, filePath); + fileStorageRepository.MoveFile(srcFilePath, filePath); return await GetInfoAsync(fileId, token); } @@ -71,18 +67,14 @@ namespace AsbCloudInfrastructure.Services //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); + await fileStorageRepository.CopyFileAsync(filePath, fileStream, token); return await GetInfoAsync(fileId, token); } private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId) { - return Path.Combine(RootPath, $"{idWell}", + return Path.Combine(fileStorageRepository.RootPath, $"{idWell}", $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}"); } @@ -95,10 +87,7 @@ namespace AsbCloudInfrastructure.Services 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); - } + fileStorageRepository.FileExists(fullPath, relativePath); return dto; } @@ -119,8 +108,7 @@ namespace AsbCloudInfrastructure.Services 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); + fileStorageRepository.DeleteFile(fileName); } return files.Any() ? 1 : 0; @@ -137,7 +125,7 @@ namespace AsbCloudInfrastructure.Services 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}"); + Path.Combine(fileStorageRepository.RootPath, idWell.ToString(), idCategory.ToString(), $"{idFile}{dotExtention}"); public Task MarkFileMarkAsDeletedAsync(int idMark, CancellationToken token) @@ -153,12 +141,9 @@ namespace AsbCloudInfrastructure.Services 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); - } + fileStorageRepository.FileExists(fullPath, relativePath); } - + return result; } diff --git a/AsbCloudInfrastructure/Services/ReportService.cs b/AsbCloudInfrastructure/Services/ReportService.cs index 53d8653a..7d60f852 100644 --- a/AsbCloudInfrastructure/Services/ReportService.cs +++ b/AsbCloudInfrastructure/Services/ReportService.cs @@ -67,7 +67,8 @@ namespace AsbCloudInfrastructure.Services generator.Make(reportFileName); var fileRepository = new FileRepository(context); - var fileService = new FileService(fileRepository); + var fileStorageRepository = new FileStorageRepository(); + var fileService = new FileService(fileRepository, fileStorageRepository); var fileInfo = await fileService.MoveAsync(idWell, idUser, ReportCategoryId, reportFileName, reportFileName, token); progressHandler.Invoke(new diff --git a/AsbCloudWebApi.Tests/RepositoryFactory.cs b/AsbCloudWebApi.Tests/RepositoryFactory.cs index 8495751c..a8588dda 100644 --- a/AsbCloudWebApi.Tests/RepositoryFactory.cs +++ b/AsbCloudWebApi.Tests/RepositoryFactory.cs @@ -1,9 +1,7 @@ using AsbCloudApp.Services; using Moq; -using System; using System.Collections.Generic; using System.Linq; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -11,7 +9,7 @@ namespace AsbCloudWebApi.Tests { public class RepositoryFactory { - public static Mock Make(IList data) + public static Mock Make(ICollection data) where TDto : AsbCloudApp.Data.IId where TRepository : class, ICrudService { diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs index bf3c6442..828f19ae 100644 --- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs +++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs @@ -1,6 +1,7 @@ using AsbCloudApp.Data; using AsbCloudApp.Services; using AsbCloudDb.Model; +using AsbCloudInfrastructure.Repository; using AsbCloudInfrastructure.Services; using DocumentFormat.OpenXml.Spreadsheet; using DocumentFormat.OpenXml.Wordprocessing; @@ -136,7 +137,11 @@ namespace AsbCloudWebApi.Tests.ServicesTests return Task.FromResult(result); }); - fileService = new FileService(repositoryMock.Object); + var storageRepositoryMock = new Mock(); + + storageRepositoryMock.Setup(x => x.RootPath).Returns("files"); + + fileService = new FileService(repositoryMock.Object, storageRepositoryMock.Object); } [Fact] @@ -147,27 +152,23 @@ namespace AsbCloudWebApi.Tests.ServicesTests } [Fact] - public async Task GetInfoAsync_throws_FileNotFoundException() + public async Task GetInfoAsync_returns_FileInfo() { - await Assert.ThrowsAsync(async () => - { - await fileService.GetInfoAsync(1743, CancellationToken.None); - }); + var data = await fileService.GetInfoAsync(1742, CancellationToken.None); + Assert.NotNull(data); } [Fact] - public async Task GetInfoByIdsAsync_throws_FileNotFoundException() + public async Task GetInfoByIdsAsync_returns_FileInfo() { - await Assert.ThrowsAsync(async () => - { - await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); - }); + var data = await fileService.GetInfoByIdsAsync(new int[] { 1742, 1743 }, CancellationToken.None); + Assert.NotNull(data); } [Fact] public async Task SaveAsync_returns_FileInfoa() { - var stream = new FileStream("D:\\test\\test.txt", FileMode.Open); + using var stream = new MemoryStream(); var data = await fileService.SaveAsync(90, 1, 10040, "test.txt", stream, CancellationToken.None); Assert.NotNull(data); }