forked from ddrilling/AsbCloudServer
Степанов Дмитрий Александрович
e56530a10f
1. Добавил сервисы и репозитории для инфструкций 2. Добавил контроллеры 3. Обновил конфиг
202 lines
6.9 KiB
C#
202 lines
6.9 KiB
C#
using System;
|
||
using System.Collections.Generic;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Threading;
|
||
using System.Threading.Tasks;
|
||
using AsbCloudApp.Data.Manuals;
|
||
using AsbCloudApp.Exceptions;
|
||
using AsbCloudApp.Repositories;
|
||
using AsbCloudApp.Services;
|
||
using AsbCloudDb.Model;
|
||
using Microsoft.Extensions.Configuration;
|
||
|
||
namespace AsbCloudInfrastructure.Services;
|
||
|
||
public class ManualCatalogService : IManualCatalogService
|
||
{
|
||
private readonly IEnumerable<string> validExtensions = new[]
|
||
{
|
||
".pdf",
|
||
".mp4"
|
||
};
|
||
|
||
private readonly string directoryFiles;
|
||
private readonly IFileStorageRepository fileStorageRepository;
|
||
private readonly IManualFolderRepository manualFolderRepository;
|
||
private readonly IManualRepository manualRepository;
|
||
private readonly IFileCategoryRepository fileCategoryRepository;
|
||
|
||
public ManualCatalogService(IFileStorageRepository fileStorageRepository,
|
||
IManualFolderRepository manualFolderRepository,
|
||
IManualRepository manualRepository,
|
||
IFileCategoryRepository fileCategoryRepository,
|
||
IConfiguration configuration)
|
||
{
|
||
this.fileStorageRepository = fileStorageRepository;
|
||
this.manualFolderRepository = manualFolderRepository;
|
||
this.manualRepository = manualRepository;
|
||
this.fileCategoryRepository = fileCategoryRepository;
|
||
directoryFiles = configuration.GetValue<string>("DirectoryManualFiles");
|
||
|
||
if (string.IsNullOrWhiteSpace(directoryFiles))
|
||
directoryFiles = "manuals";
|
||
}
|
||
|
||
public async Task<int> SaveFileAsync(int? idCategory, int? idFolder, string name, Stream stream,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
var extension = Path.GetExtension(name);
|
||
|
||
if (!validExtensions.Contains(extension))
|
||
throw new ArgumentInvalidException(
|
||
$"Невозможно загрузить файл с расширением '{extension}'. Допустимые форматы файлов: {string.Join(", ", validExtensions)}",
|
||
extension);
|
||
|
||
var path = await BuildFilePathAsync(idCategory, idFolder, name, cancellationToken);
|
||
|
||
await fileStorageRepository.SaveFileAsync(path,
|
||
stream,
|
||
cancellationToken);
|
||
|
||
var manual = new ManualDto
|
||
{
|
||
Name = name,
|
||
DateDownload = DateTime.UtcNow,
|
||
IdFolder = idFolder,
|
||
IdCategory = idCategory
|
||
};
|
||
|
||
return await manualRepository.InsertAsync(manual, cancellationToken);
|
||
}
|
||
|
||
public async Task<int> AddFolderAsync(string name, int? idParent, int idCategory,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
if (idParent.HasValue)
|
||
{
|
||
var parent = await manualFolderRepository.GetOrDefaultAsync(idParent.Value, cancellationToken)
|
||
?? throw new ArgumentInvalidException("Родительской папки не существует", nameof(idParent));
|
||
|
||
if (parent.IdCategory != idCategory)
|
||
throw new ArgumentInvalidException("Категория родительской папки не соответствует текущей категории",
|
||
nameof(idCategory));
|
||
}
|
||
|
||
var manualFolder = new ManualFolderDto
|
||
{
|
||
Name = name,
|
||
IdParent = idParent,
|
||
IdCategory = idCategory,
|
||
};
|
||
|
||
if (await IsExistFolderAsync(manualFolder, cancellationToken))
|
||
throw new ArgumentInvalidException("Папка с таким названием уже существует", name);
|
||
|
||
return await manualFolderRepository.InsertAsync(manualFolder, cancellationToken);
|
||
}
|
||
|
||
public async Task UpdateFolderAsync(int id, string name, CancellationToken cancellationToken)
|
||
{
|
||
var folder = await manualFolderRepository.GetOrDefaultAsync(id, cancellationToken)
|
||
?? throw new ArgumentInvalidException($"Папки с Id: {id} не сущесвует", nameof(id));
|
||
|
||
folder.Name = name;
|
||
|
||
if (await IsExistFolderAsync(folder, cancellationToken))
|
||
throw new ArgumentInvalidException("Папка с таким названием уже существует", name);
|
||
|
||
await manualFolderRepository.UpdateAsync(folder, cancellationToken);
|
||
}
|
||
|
||
|
||
public async Task<int> DeleteFolderAsync(int id, CancellationToken cancellationToken)
|
||
{
|
||
var folder = await manualFolderRepository.GetOrDefaultAsync(id, cancellationToken);
|
||
|
||
if (folder is null)
|
||
return 0;
|
||
|
||
var path = Path.Combine(directoryFiles, folder.IdCategory.ToString(), folder.Id.ToString());
|
||
fileStorageRepository.DeleteDirectory(path);
|
||
|
||
return await manualFolderRepository.DeleteAsync(folder.Id, cancellationToken);
|
||
}
|
||
|
||
public async Task<int> DeleteFileAsync(int id, CancellationToken cancellationToken)
|
||
{
|
||
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
|
||
|
||
if (manual is null)
|
||
return 0;
|
||
|
||
var filePath = await BuildFilePathAsync(manual.IdCategory, manual.IdFolder, manual.Name,
|
||
cancellationToken);
|
||
|
||
fileStorageRepository.DeleteFile(filePath);
|
||
|
||
return await manualRepository.DeleteAsync(manual.Id, cancellationToken);
|
||
}
|
||
|
||
public async Task<(Stream stream, string fileName)?> GetFileAsync(int id, CancellationToken cancellationToken)
|
||
{
|
||
var manual = await manualRepository.GetOrDefaultAsync(id, cancellationToken);
|
||
|
||
if (manual is null)
|
||
return null;
|
||
|
||
var path = await BuildFilePathAsync(manual.IdCategory, manual.IdFolder, manual.Name, cancellationToken);
|
||
|
||
var fileStream = new FileStream(Path.GetFullPath(path), FileMode.Open);
|
||
|
||
return (fileStream, manual.Name);
|
||
}
|
||
|
||
public async Task<IEnumerable<CatalogItemManualDto>> GetCatalogAsync(CancellationToken cancellationToken)
|
||
{
|
||
var catalogItems = new List<CatalogItemManualDto>();
|
||
|
||
var categories = await fileCategoryRepository.GetAllAsync(FileCategory.IdFileCategoryTypeManuals,
|
||
cancellationToken);
|
||
|
||
foreach (var category in categories)
|
||
{
|
||
catalogItems.Add(new CatalogItemManualDto()
|
||
{
|
||
Category = category,
|
||
ManualsWithoutFolder = await manualRepository.GetManualsWithoutFolderAsync(category.Id, cancellationToken),
|
||
Folders = await manualFolderRepository.GetTreeAsync(category.Id, cancellationToken)
|
||
});
|
||
}
|
||
|
||
return catalogItems;
|
||
}
|
||
|
||
private async Task<bool> IsExistFolderAsync(ManualFolderDto folder, CancellationToken cancellationToken)
|
||
{
|
||
var existingFolder = await manualFolderRepository.GetOrDefaultAsync(folder.Name, folder.IdParent,
|
||
folder.IdCategory,
|
||
cancellationToken);
|
||
|
||
return existingFolder is not null && folder.Id != existingFolder.Id;
|
||
}
|
||
|
||
private async Task<string> BuildFilePathAsync(int? idCategory, int? idFolder, string name,
|
||
CancellationToken cancellationToken)
|
||
{
|
||
if (idFolder.HasValue)
|
||
{
|
||
var folder = await manualFolderRepository.GetOrDefaultAsync(idFolder.Value, cancellationToken)
|
||
?? throw new ArgumentInvalidException($"Папки с Id: {idFolder} не сущесвует", nameof(idFolder));
|
||
|
||
return fileStorageRepository.MakeFilePath(directoryFiles, Path.Combine(folder.IdCategory.ToString(),
|
||
folder.IdParent.ToString() ?? string.Empty,
|
||
folder.Id.ToString()), name);
|
||
}
|
||
|
||
if (!idCategory.HasValue)
|
||
throw new ArgumentInvalidException("Не указан идентификатор категории", nameof(idCategory));
|
||
|
||
return fileStorageRepository.MakeFilePath(directoryFiles, idCategory.Value.ToString(), name);
|
||
}
|
||
} |