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

179 lines
6.3 KiB
C#
Raw Normal View History

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");
if (string.IsNullOrWhiteSpace(directoryFiles))
directoryFiles = "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(
2023-09-29 12:06:46 +05:00
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))
2023-09-29 12:06:46 +05:00
throw new ArgumentInvalidException(nameof(idParent), "Родительской директории не существует");
var directory = new ManualDirectoryDto
{
Name = name,
IdParent = idParent,
};
if (await IsExistDirectoryAsync(directory, cancellationToken))
2023-09-29 12:06:46 +05:00
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)
2023-09-29 12:06:46 +05:00
?? throw new ArgumentInvalidException(nameof(id), $"Директории с Id: {id} не существует");
directory.Name = name;
if (await IsExistDirectoryAsync(directory, cancellationToken))
2023-09-29 12:06:46 +05:00
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)
{
2023-09-29 12:06:46 +05:00
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)
2023-09-29 12:06:46 +05:00
?? 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);
2023-09-29 12:06:46 +05:00
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));
}
}