DD.WellWorkover.Cloud/AsbCloudInfrastructure/Services/ManualCatalogService.cs

176 lines
6.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 Microsoft.Extensions.Configuration;
namespace AsbCloudInfrastructure.Services;
public class ManualCatalogService : IManualCatalogService
{
private const int IdFileCategory = 30000;
private readonly IEnumerable<string> validExtensions = new[]
{
".pdf",
".mp4"
};
private readonly string directoryFiles;
private readonly IFileStorageRepository fileStorageRepository;
private readonly IManualDirectoryRepository manualDirectoryRepository;
private readonly ICrudRepository<ManualDto> manualRepository;
public ManualCatalogService(IFileStorageRepository fileStorageRepository,
IManualDirectoryRepository manualDirectoryRepository,
ICrudRepository<ManualDto> manualRepository,
IConfiguration configuration)
{
this.fileStorageRepository = fileStorageRepository;
this.manualDirectoryRepository = manualDirectoryRepository;
this.manualRepository = manualRepository;
directoryFiles = configuration.GetValue<string>("DirectoryManualFiles", "manuals")!;
}
public async Task<int> SaveFileAsync(int idDirectory, int idAuthor, string name, Stream stream, CancellationToken cancellationToken)
{
var extension = Path.GetExtension(name);
if (!validExtensions.Contains(extension))
throw new ArgumentInvalidException(
nameof(name),
$"Невозможно загрузить файл с расширением '{extension}'. Допустимые форматы файлов: {string.Join(", ", validExtensions)}");
var path = await BuildFilePathAsync(idDirectory, name, cancellationToken);
await fileStorageRepository.SaveFileAsync(path, stream, cancellationToken);
var manual = new ManualDto
{
Name = name,
DateDownload = DateTimeOffset.UtcNow,
IdDirectory = idDirectory,
IdCategory = IdFileCategory,
IdAuthor = idAuthor
};
return await manualRepository.InsertAsync(manual, cancellationToken);
}
public async Task<int> AddDirectoryAsync(string name, int? idParent, CancellationToken cancellationToken)
{
if (idParent.HasValue && !await manualDirectoryRepository.IsExistsAsync(idParent.Value, cancellationToken))
throw new ArgumentInvalidException(nameof(idParent), "Родительской директории не существует");
var directory = new ManualDirectoryDto
{
Name = name,
IdParent = idParent,
};
if (await IsExistDirectoryAsync(directory, cancellationToken))
throw new ArgumentInvalidException(name, "Директория с таким названием уже существует");
return await manualDirectoryRepository.InsertAsync(directory, cancellationToken);
}
public async Task UpdateDirectoryAsync(int id, string name, CancellationToken cancellationToken)
{
var directory = await manualDirectoryRepository.GetOrDefaultAsync(id, cancellationToken)
?? throw new ArgumentInvalidException(nameof(id), $"Директории с Id: {id} не существует");
directory.Name = name;
if (await IsExistDirectoryAsync(directory, cancellationToken))
throw new ArgumentInvalidException(name, "Директория с таким названием уже существует");
await manualDirectoryRepository.UpdateAsync(directory, cancellationToken);
}
public async Task<int> DeleteDirectoryAsync(int id, CancellationToken cancellationToken)
{
var directory = await manualDirectoryRepository.GetOrDefaultAsync(id, cancellationToken);
if (directory is null)
return 0;
var path = fileStorageRepository.MakeFilePath(directoryFiles, IdFileCategory.ToString(),
await BuildDirectoryPathAsync(id, cancellationToken));
try
{
fileStorageRepository.DeleteDirectory(path, true);
}
catch (InvalidOperationException ex)
{
throw new ArgumentInvalidException(nameof(id), ex.Message);
}
return await manualDirectoryRepository.DeleteAsync(directory.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.IdDirectory, 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.IdDirectory, manual.Name, cancellationToken);
var fileStream = new FileStream(path, FileMode.Open);
return (fileStream, manual.Name);
}
private async Task<bool> IsExistDirectoryAsync(ManualDirectoryDto directory, CancellationToken cancellationToken)
{
var existingDirectory = await manualDirectoryRepository.GetOrDefaultAsync(directory.Name, directory.IdParent,
cancellationToken);
return existingDirectory is not null && directory.Id != existingDirectory.Id;
}
private async Task<string> BuildDirectoryPathAsync(int idDirectory, CancellationToken cancellationToken)
{
var directiories = await manualDirectoryRepository.GetAllAsync(cancellationToken);
var directory = directiories.FirstOrDefault(d => d.Id == idDirectory)
?? throw new ArgumentInvalidException(nameof(idDirectory), $"Директории с Id: {idDirectory} не существует");
var pathSegments = new List<int> { directory.Id };
while (directory.IdParent.HasValue)
{
directory = directiories.FirstOrDefault(d => d.Id == directory.IdParent.Value);
pathSegments.Insert(0, directory!.Id);
}
return string.Join("/", pathSegments);
}
private async Task<string> BuildFilePathAsync(int idDirectory, string name, CancellationToken cancellationToken)
{
var directoryPath = await BuildDirectoryPathAsync(idDirectory, cancellationToken);
return fileStorageRepository.MakeFilePath(directoryFiles, IdFileCategory.ToString(), Path.Combine(directoryPath, name));
}
}