diff --git a/AsbCloudApp/Repositories/IFileRepository.cs b/AsbCloudApp/Repositories/IFileRepository.cs
index e36d1001..488630ae 100644
--- a/AsbCloudApp/Repositories/IFileRepository.cs
+++ b/AsbCloudApp/Repositories/IFileRepository.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using System;
using System.Collections.Generic;
@@ -7,6 +8,7 @@ using System.Threading.Tasks;
namespace AsbCloudApp.Repositories
{
+#nullable enable
///
/// Сервис доступа к файлам
///
@@ -24,19 +26,10 @@ namespace AsbCloudApp.Repositories
///
/// Получить список файлов в контейнере
///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
+ ///
///
///
- Task> GetInfosAsync(int idWell,
- int idCategory, string companyName = default, string fileName = default, DateTime begin = default,
- DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default);
+ Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default);
///
/// Пометить файл как удаленный
@@ -90,9 +83,10 @@ namespace AsbCloudApp.Repositories
///
/// Получение файлов по скважине
///
- ///
+ ///
///
///
- Task> GetInfosByWellIdAsync(int idWell, CancellationToken token);
+ Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token);
}
+#nullable disable
}
diff --git a/AsbCloudApp/Repositories/IFileStorageRepository.cs b/AsbCloudApp/Repositories/IFileStorageRepository.cs
index 9d821861..72c11d21 100644
--- a/AsbCloudApp/Repositories/IFileStorageRepository.cs
+++ b/AsbCloudApp/Repositories/IFileStorageRepository.cs
@@ -1,9 +1,12 @@
-using System.IO;
+using AsbCloudApp.Data;
+using System.Collections.Generic;
+using System.IO;
using System.Threading;
using System.Threading.Tasks;
namespace AsbCloudApp.Repositories
{
+#nullable enable
///
/// Репозиторий хранения фалов
///
@@ -47,5 +50,31 @@ namespace AsbCloudApp.Repositories
///
///
bool FileExists(string fullPath, string fileName);
+
+ ///
+ /// Удаление всех файлов с диска о которых нет информации в базе
+ ///
+ ///
+ ///
+ int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles);
+
+ ///
+ /// Вывод списка всех файлов из базы, для которых нет файла на диске
+ ///
+ ///
+ ///
+ ///
+ IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files);
+
+ ///
+ /// Получение пути к файлу
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId);
}
+#nullable disable
}
diff --git a/AsbCloudApp/Requests/FileServiceRequest.cs b/AsbCloudApp/Requests/FileServiceRequest.cs
new file mode 100644
index 00000000..bc561bdd
--- /dev/null
+++ b/AsbCloudApp/Requests/FileServiceRequest.cs
@@ -0,0 +1,60 @@
+using System;
+using System.ComponentModel.DataAnnotations;
+
+namespace AsbCloudApp.Requests
+{
+#nullable enable
+ ///
+ /// Параметры запроса для файлового сервиса
+ ///
+ public class FileServiceRequest : RequestBase
+ {
+ ///
+ /// Идентификатор скважины
+ ///
+ [Required]
+ public int? IdWell { get; set; }
+
+ ///
+ /// Идентификатор категории файла
+ ///
+ [Required]
+ public int? IdCategory { get; set; }
+
+ ///
+ /// Наименование компании
+ ///
+ public string? CompanyName { get; set; }
+
+ ///
+ /// Имя файла
+ ///
+ public string? FileName { get; set; }
+
+ ///
+ /// Дата начала периода
+ ///
+ public DateTime? Begin { get; set; }
+
+ ///
+ /// Дата окончания периода
+ ///
+ public DateTime? End { get; set; }
+
+ ///
+ /// Идентификатор файла
+ ///
+ public int? IdFile { get; set; }
+
+ ///
+ /// Идентификатор отметки
+ ///
+ public int? IdMark { get; set; }
+
+ ///
+ /// Признак удаления
+ ///
+ public bool? IsDeleted { get; set; }
+ }
+#nullable disable
+}
diff --git a/AsbCloudApp/Services/FileService.cs b/AsbCloudApp/Services/FileService.cs
index b27c4383..934e5dc3 100644
--- a/AsbCloudApp/Services/FileService.cs
+++ b/AsbCloudApp/Services/FileService.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
using System;
using System.Collections.Generic;
using System.IO;
@@ -9,6 +10,7 @@ using System.Threading.Tasks;
namespace AsbCloudApp.Services
{
+#nullable enable
///
/// Сервис доступа к файлам
///
@@ -56,7 +58,7 @@ namespace AsbCloudApp.Services
var fileId = await fileRepository.InsertAsync(dto, token)
.ConfigureAwait(false);
- string filePath = MakeFilePath(idWell, idCategory, destinationFileName, fileId);
+ string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, destinationFileName, fileId);
fileStorageRepository.MoveFile(srcFilePath, filePath);
return await GetInfoAsync(fileId, token);
@@ -89,7 +91,7 @@ namespace AsbCloudApp.Services
.ConfigureAwait(false);
//save stream to disk
- string filePath = MakeFilePath(idWell, idCategory, fileFullName, fileId);
+ string filePath = fileStorageRepository.MakeFilePath(idWell, idCategory, fileFullName, fileId);
await fileStorageRepository.CopyFileAsync(filePath, fileStream, token);
return await GetInfoAsync(fileId, token);
@@ -215,20 +217,11 @@ namespace AsbCloudApp.Services
///
/// Получить список файлов в контейнере
///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- ///
+ ///
///
///
- public async Task> GetInfosAsync(int idWell,
- int idCategory, string companyName = default, string fileName = default, DateTime begin = default,
- DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default)
- => await fileRepository.GetInfosAsync(idWell, idCategory, companyName, fileName, begin, end, skip, take, token)
+ public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token)
+ => await fileRepository.GetInfosAsync(request, token)
.ConfigureAwait(false);
///
@@ -275,7 +268,7 @@ namespace AsbCloudApp.Services
///
/// получить инфо о файле по метке
///
- ///
+ ///
///
///
public async Task MarkFileMarkAsDeletedAsync(IEnumerable idsMarks, CancellationToken token)
@@ -289,7 +282,7 @@ namespace AsbCloudApp.Services
///
///
public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token)
- => await fileRepository.GetInfosByWellIdAsync(idWell, token)
+ => await fileRepository.GetInfosByWellIdAsync(new FileServiceRequest { IdWell = idWell, IsDeleted = false }, token)
.ConfigureAwait(false);
///
@@ -303,10 +296,58 @@ namespace AsbCloudApp.Services
=> await fileRepository.GetInfosByCategoryAsync(idWell, idCategory, token)
.ConfigureAwait(false);
- private string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
+ ///
+ /// Удаление всех файлов по скважине помеченных как удаленные
+ ///
+ ///
+ ///
+ ///
+ public async Task DeleteFilesFromDbMarkedDeletionByIdWell(int idWell, CancellationToken token)
{
- return Path.Combine(fileStorageRepository.RootPath, $"{idWell}",
- $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
+ var files = await fileRepository.GetInfosByWellIdAsync(
+ new FileServiceRequest
+ {
+ IdWell = idWell,
+ IsDeleted = true
+ },
+ token);
+ var result = await DeleteAsync(files.Select(x => x.Id), token);
+ return result;
+ }
+
+ ///
+ /// Удаление всех файлов с диска о которых нет информации в базе
+ ///
+ ///
+ ///
+ public async Task DeleteFilesNotExistStorage(int idWell, CancellationToken token)
+ {
+ var files = await fileRepository.GetInfosByWellIdAsync(
+ new FileServiceRequest
+ {
+ IdWell = idWell
+ },
+ token);
+ var result = await Task.FromResult(fileStorageRepository.DeleteFilesNotExistStorage(idWell, files.Select(x => x.Id)));
+ return result;
+ }
+
+ ///
+ /// Вывод списка всех файлов из базы, для которых нет файла на диске
+ ///
+ ///
+ ///
+ public async Task> GetListFilesNotDisc(int idWell, CancellationToken token)
+ {
+ var files = await fileRepository.GetInfosByWellIdAsync(
+ new FileServiceRequest
+ {
+ IdWell = idWell
+ },
+ token);
+ var result = fileStorageRepository.GetListFilesNotDisc(idWell, files);
+ return result;
}
}
+#nullable disable
}
diff --git a/AsbCloudInfrastructure/Repository/FileRepository.cs b/AsbCloudInfrastructure/Repository/FileRepository.cs
index 0cca5b8b..16367b09 100644
--- a/AsbCloudInfrastructure/Repository/FileRepository.cs
+++ b/AsbCloudInfrastructure/Repository/FileRepository.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
@@ -12,6 +13,7 @@ using System.Threading.Tasks;
namespace AsbCloudInfrastructure.Repository
{
+#nullable enable
public class FileRepository : IFileRepository
{
private readonly IQueryable dbSetConfigured;
@@ -41,22 +43,23 @@ namespace AsbCloudInfrastructure.Repository
return dtos;
}
- public async Task> GetInfosAsync(int idWell,
- int idCategory, string companyName = default, string fileName = default, DateTime begin = default,
- DateTime end = default, int skip = 0, int take = 32, CancellationToken token = default)
+ public async Task> GetInfosAsync(FileServiceRequest request, CancellationToken token = default)
{
var query = dbSetConfigured
- .Where(e => e.IdWell == idWell &&
- e.IdCategory == idCategory &&
+ .Where(e => e.IdWell == request.IdWell &&
+ e.IdCategory == request.IdCategory &&
!e.IsDeleted);
- if (!string.IsNullOrEmpty(companyName))
+ if (request.CompanyName is not null)
query = query.Where(e => (e.Author == null) ||
(e.Author.Company == null) ||
- e.Author.Company.Caption.Contains(companyName));
+ e.Author.Company.Caption.Contains(request.CompanyName));
- if (!string.IsNullOrEmpty(fileName))
- query = query.Where(e => e.Name.ToLower().Contains(fileName.ToLower()));
+ if (request.FileName is not null)
+ query = query.Where(e => e.Name.ToLower().Contains(request.FileName.ToLower()));
+
+ var skip = request.Skip ?? 0;
+ var take = request.Take ?? 32;
var firstFile = await query.FirstOrDefaultAsync(token);
if (firstFile is null)
@@ -69,15 +72,15 @@ namespace AsbCloudInfrastructure.Repository
var timezoneOffset = firstFile.Well.Timezone?.Hours ?? 5;
- if (begin != default)
+ if (request.Begin is not null)
{
- var beginUtc = begin.ToUtcDateTimeOffset(timezoneOffset);
+ var beginUtc = request.Begin.Value.ToUtcDateTimeOffset(timezoneOffset);
query = query.Where(e => e.UploadDate >= beginUtc);
}
- if (end != default)
+ if (request.End is not null)
{
- var endUtc = end.ToUtcDateTimeOffset(timezoneOffset);
+ var endUtc = request.End.Value.ToUtcDateTimeOffset(timezoneOffset);
query = query.Where(e => e.UploadDate <= endUtc);
}
@@ -201,10 +204,13 @@ namespace AsbCloudInfrastructure.Repository
return await db.SaveChangesAsync(token);
}
- public async Task> GetInfosByWellIdAsync(int idWell, CancellationToken token)
+ public async Task> GetInfosByWellIdAsync(FileServiceRequest request, CancellationToken token)
{
- var entities = await dbSetConfigured
- .Where(e => e.IdWell == idWell && e.IsDeleted == false)
+ var query = dbSetConfigured.Where(e => e.IdWell == request.IdWell);
+ if (request.IsDeleted is not null)
+ query = query.Where(x => x.IsDeleted == request.IsDeleted);
+
+ var entities = await query
.AsNoTracking()
.ToListAsync(token)
.ConfigureAwait(false);
@@ -302,4 +308,5 @@ namespace AsbCloudInfrastructure.Repository
throw new NotImplementedException();
}
}
+#nullable disable
}
diff --git a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs
index 7466f3a3..2b1f84f1 100644
--- a/AsbCloudInfrastructure/Repository/FileStorageRepository.cs
+++ b/AsbCloudInfrastructure/Repository/FileStorageRepository.cs
@@ -1,11 +1,17 @@
-using AsbCloudApp.Exceptions;
+using AsbCloudApp.Data;
+using AsbCloudApp.Exceptions;
using AsbCloudApp.Repositories;
+using System;
+using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using FileInfo = System.IO.FileInfo;
namespace AsbCloudInfrastructure.Repository
{
+#nullable enable
public class FileStorageRepository : IFileStorageRepository
{
public string RootPath { get; private set; }
@@ -51,9 +57,68 @@ namespace AsbCloudInfrastructure.Repository
return true;
}
- private void CreateDirectory(string filePath)
+ public string MakeFilePath(int idWell, int idCategory, string fileFullName, int fileId)
+ {
+ return Path.Combine(RootPath, $"{idWell}",
+ $"{idCategory}", $"{fileId}" + $"{Path.GetExtension(fileFullName)}");
+ }
+
+ public int DeleteFilesNotExistStorage(int idWell, IEnumerable idsFiles)
+ {
+ var allFilesPath = GetFilesPath(idWell);
+ var resutl = 0;
+
+ foreach (var filePath in allFilesPath)
+ {
+ var idFile = Path.GetFileNameWithoutExtension(filePath);
+ if (!idsFiles.Any(x => x.ToString() == idFile))
+ {
+ File.Delete(filePath);
+ resutl++;
+ }
+ }
+
+ return resutl;
+ }
+
+ public IEnumerable GetListFilesNotDisc(int idWell, IEnumerable files)
+ {
+ var resutl = new List();
+ var idsFilesStorage = GetIdsFiles(idWell);
+
+ foreach (var file in files)
+ {
+ if (!idsFilesStorage.Any(x => x == file.Id))
+ resutl.Add(file);
+ }
+
+ return resutl;
+ }
+
+ private IEnumerable GetIdsFiles(int idWell)
+ {
+ var result = new List();
+ var allFilesPath = GetFilesPath(idWell);
+
+ foreach (var filePath in allFilesPath)
+ {
+ var idFileStr = Path.GetFileNameWithoutExtension(filePath);
+ result.Add(Convert.ToInt32(idFileStr));
+ }
+
+ return result;
+ }
+
+ private IEnumerable GetFilesPath(int idWell)
+ {
+ var path = Path.Combine(RootPath, $"{idWell}");
+ return Directory.GetFiles(path, "*.*", SearchOption.AllDirectories);
+ }
+
+ private static void CreateDirectory(string filePath)
{
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
}
}
+#nullable disable
}
diff --git a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs
index 025cc7bb..91b2af74 100644
--- a/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs
+++ b/AsbCloudWebApi.Tests/ServicesTests/FileServiceTest.cs
@@ -1,5 +1,6 @@
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
+using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
@@ -115,9 +116,9 @@ namespace AsbCloudWebApi.Tests.ServicesTests
return Task.FromResult(result);
});
- repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny()))
- .Returns((int idWell, CancellationToken token) => {
- var data = Files.Where(x => x.IdWell == idWell);
+ repositoryMock.Setup(x => x.GetInfosByWellIdAsync(It.IsAny(), It.IsAny()))
+ .Returns((FileServiceRequest request, CancellationToken token) => {
+ var data = Files.Where(x => x.IdWell == request.IdWell);
return Task.FromResult(data);
});
diff --git a/AsbCloudWebApi/Controllers/FileController.cs b/AsbCloudWebApi/Controllers/FileController.cs
index 378b5a50..499129f2 100644
--- a/AsbCloudWebApi/Controllers/FileController.cs
+++ b/AsbCloudWebApi/Controllers/FileController.cs
@@ -1,4 +1,5 @@
using AsbCloudApp.Data;
+using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
@@ -12,6 +13,7 @@ using System.Threading.Tasks;
namespace AsbCloudWebApi.Controllers
{
+#nullable enable
///
/// Хранение файлов
///
@@ -70,38 +72,27 @@ namespace AsbCloudWebApi.Controllers
///
/// Возвращает информацию о файлах для скважины в выбраной категории
///
- /// id скважины
- /// id категории файла
- /// id компаний для фильтрации возвращаемых файлов
- /// часть имени файла для поиска
- /// дата начала
- /// дата окончания
- /// для пагинации кол-во записей пропустить
- /// для пагинации кол-во записей взять
+ ///
/// Токен отмены задачи
/// Список информации о файлах в этой категории
[HttpGet]
+ [Route("/api/files")]
[Permission]
[ProducesResponseType(typeof(PaginationContainer), (int)System.Net.HttpStatusCode.OK)]
public async Task GetFilesInfoAsync(
- [FromRoute] int idWell,
- int idCategory = default,
- string companyName = default,
- string fileName = default,
- DateTime begin = default,
- DateTime end = default,
- int skip = 0,
- int take = 32,
+ [FromQuery] FileServiceRequest request,
CancellationToken token = default)
{
int? idCompany = User.GetCompanyId();
- if (idCompany is null || !await wellService.IsCompanyInvolvedInWellAsync((int)idCompany,
- idWell, token).ConfigureAwait(false))
+ if (request.IdWell is null || request.IdCategory is null || idCompany is null)
return Forbid();
- var filesInfo = await fileService.GetInfosAsync(idWell, idCategory,
- companyName, fileName, begin, end, skip, take, token).ConfigureAwait(false);
+ if (!await wellService.IsCompanyInvolvedInWellAsync(idCompany.Value,
+ request.IdWell.Value, token).ConfigureAwait(false))
+ return Forbid();
+
+ var filesInfo = await fileService.GetInfosAsync(request, token).ConfigureAwait(false);
return Ok(filesInfo);
}
@@ -254,4 +245,5 @@ namespace AsbCloudWebApi.Controllers
}
}
}
+#nullable disable
}