CS2-38: Добавлены модель, контроллер и сервис для сохранения и отправки файлов по категориям

This commit is contained in:
KharchenkoVV 2021-07-23 17:40:31 +05:00
parent 1d69ddf4e5
commit 99242f6995
9 changed files with 318 additions and 15 deletions

View File

@ -0,0 +1,13 @@
using System;
namespace AsbCloudApp.Data
{
public class FilePropertiesDto
{
public int Id { get; set; }
public string Name { get; set; }
public int IdCategory { get; set; }
public DateTime UploadDate { get; set; }
public string UserName { get; set; }
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using AsbCloudApp.Data;
namespace AsbCloudApp.Services
{
public interface IFileService
{
string RootPath { get; }
IDictionary<string, int> SaveFilesPropertiesToDb(int wellId,
int idCategory, IEnumerable<(string fileName, int idCategory,
DateTime date, int idUser)> filesInfo);
IEnumerable<FilePropertiesDto> GetFilesInfo(int wellId, int idCategory);
(int Id, string Name, int IdCategory)? GetFileInfo(int fileId);
}
}

View File

@ -25,6 +25,8 @@ namespace AsbCloudDb.Model
public virtual DbSet<UserRole> UserRoles { get; set; }
public virtual DbSet<Well> Wells { get; set; }
public virtual DbSet<Report> Reports { get; set; }
public virtual DbSet<File> Files { get; set; }
public virtual DbSet<FileCategory> FileCategories { get; set; }
public virtual DbSet<Operation> Operations { get; set; }
public virtual DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }
public virtual DbSet<WellSection> SectionAnalysis { get; set; }
@ -209,6 +211,24 @@ namespace AsbCloudDb.Model
new Operation {Id = 17, Name = "На поверхности" }
});
});
modelBuilder.Entity<FileCategory>(entity =>
{
entity.HasData(new List<FileCategory> {
new FileCategory {Id = 1, Name = "Растворный сервис"},
new FileCategory {Id = 2, Name = "Цементирование"},
new FileCategory {Id = 3, Name = "ННБ"},
new FileCategory {Id = 4, Name = "ГТИ"},
new FileCategory {Id = 5, Name = "Документы по скважине"},
new FileCategory {Id = 6, Name = "Супервайзер"},
new FileCategory {Id = 7, Name = "Мастер"},
new FileCategory {Id = 8, Name = "Последние данные"},
new FileCategory {Id = 9, Name = "Последний замер бурового раствора"},
new FileCategory {Id = 10, Name = "Шламограмма"},
new FileCategory {Id = 11, Name = "Последние данные ННБ"},
new FileCategory {Id = 12, Name = "Рапорт"}
});
});
}
private static void FillDemoData(ModelBuilder modelBuilder)
@ -240,21 +260,6 @@ namespace AsbCloudDb.Model
});
});
modelBuilder.Entity<Well>(entity =>
{
entity.HasData(new List<Well> {
new Well{Id = 1, IdCluster = 1, Caption = "скв 16314", Latitude = 60.8705722222222, Longitude = 70.3811888888889},
new Well{Id = 2, IdCluster = 1, Caption = "скв 16311", Latitude = 60.8705722222222, Longitude = 70.3811888888889},
new Well{Id = 3, IdCluster = 2, Caption = "скв 16315", Latitude = 60.8205750000000, Longitude = 70.1343833333334},
new Well{Id = 4, IdCluster = 2, Caption = "скв 16318", Latitude = 60.8205750000000, Longitude = 70.1343833333334},
new Well{Id = 5, IdCluster = 3, Caption = "скв 16310", Latitude = 60.8100666666667, Longitude = 69.7778388888889},
new Well{Id = 6, IdCluster = 4, Caption = "скв 16316", Latitude = 60.8928805555556, Longitude = 70.3272055555556},
new Well{Id = 7, IdCluster = 5, Caption = "скв 16312", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
new Well{Id = 8, IdCluster = 5, Caption = "скв 16313", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
new Well{Id = 9, IdCluster = 5, Caption = "скв 42669", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
});
});
modelBuilder.Entity<Telemetry>(entity =>
{
entity.HasData(new List<Telemetry>{
@ -278,6 +283,21 @@ namespace AsbCloudDb.Model
});
});
modelBuilder.Entity<Well>(entity =>
{
entity.HasData(new List<Well> {
new Well{Id = 1, IdCluster = 1, IdTelemetry = 1, Caption = "скв 16314", Latitude = 60.8705722222222, Longitude = 70.3811888888889},
new Well{Id = 2, IdCluster = 1, Caption = "скв 16311", Latitude = 60.8705722222222, Longitude = 70.3811888888889},
new Well{Id = 3, IdCluster = 2, Caption = "скв 16315", Latitude = 60.8205750000000, Longitude = 70.1343833333334},
new Well{Id = 4, IdCluster = 2, Caption = "скв 16318", Latitude = 60.8205750000000, Longitude = 70.1343833333334},
new Well{Id = 5, IdCluster = 3, Caption = "скв 16310", Latitude = 60.8100666666667, Longitude = 69.7778388888889},
new Well{Id = 6, IdCluster = 4, Caption = "скв 16316", Latitude = 60.8928805555556, Longitude = 70.3272055555556},
new Well{Id = 7, IdCluster = 5, Caption = "скв 16312", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
new Well{Id = 8, IdCluster = 5, Caption = "скв 16313", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
new Well{Id = 9, IdCluster = 5, Caption = "скв 42669", Latitude = 60.6672055555556, Longitude = 69.6603861111111},
});
});
modelBuilder.Entity<RelationCompanyWell>(entity => {
entity.HasData(new List<RelationCompanyWell> {
new RelationCompanyWell{ IdWell = 1, IdCompany = 1},

30
AsbCloudDb/Model/File.cs Normal file
View File

@ -0,0 +1,30 @@
using Microsoft.EntityFrameworkCore;
using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model
{
[Table("t_files"), Comment("Файлы всех категорий")]
public class File : IId
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("name"), Comment("Название файла")]
public string Name { get; set; }
[Column("id_well"), Comment("id скважины")]
public int IdWell { get; set; }
[Column("id_category"), Comment("id категории файла")]
public int IdCategory { get; set; }
[Column("date", TypeName = "timestamp with time zone")]
public DateTime Date { get; set; }
[Column("id_user"), Comment("Id пользователя, загрузившего файл")]
public int IdUser { get; set; }
}
}

View File

@ -0,0 +1,17 @@
using Microsoft.EntityFrameworkCore;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace AsbCloudDb.Model
{
[Table("t_file_categories"), Comment("Категории файлов")]
public class FileCategory : IId
{
[Key]
[Column("id")]
public int Id { get; set; }
[Column("name"), Comment("Название категории")]
public string Name { get; set; }
}
}

View File

@ -21,6 +21,8 @@ namespace AsbCloudDb.Model
DbSet<Well> Wells { get; set; }
DbSet<UserRole> UserRoles { get; set; }
DbSet<Report> Reports { get; set; }
DbSet<File> Files { get; set; }
DbSet<FileCategory> FileCategories { get; set; }
DbSet<Operation> Operations { get; set; }
DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }

View File

@ -37,6 +37,7 @@ namespace AsbCloudInfrastructure
services.AddTransient<ITelemetryUserService, TelemetryUserService>();
services.AddTransient<IReportService, ReportService>();
services.AddTransient<IAnalyticsService, AnalyticsService>();
services.AddTransient<IFileService, FileService>();
return services;
}

View File

@ -0,0 +1,69 @@
using System;
using System.Linq;
using System.Collections.Generic;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
namespace AsbCloudInfrastructure.Services
{
public class FileService : IFileService
{
public string RootPath { get; private set; }
private readonly IAsbCloudDbContext db;
public FileService(IAsbCloudDbContext db)
{
RootPath = "files";
this.db = db;
}
public IDictionary<string, int> SaveFilesPropertiesToDb(int wellId, int idCategory,
IEnumerable<(string fileName, int idCategory, DateTime date, int idUser)> filesInfo)
{
var fileIdsToNames = new Dictionary<string, int>();
foreach(var fileInfo in filesInfo)
{
var file = new File()
{
Name = fileInfo.fileName,
IdCategory = fileInfo.idCategory,
Date = fileInfo.date,
IdUser = fileInfo.idUser
};
db.Files.Add(file);
db.SaveChanges();
fileIdsToNames.Add(file.Name, file.Id);
}
return fileIdsToNames;
}
public IEnumerable<FilePropertiesDto> GetFilesInfo(int wellId, int idCategory)
{
var fileInfoFromDb = db.Files.Where(f => f.IdWell == wellId &&
f.IdCategory == idCategory).Select(file => new FilePropertiesDto
{
Id = file.Id,
Name = file.Name,
IdCategory = file.IdCategory,
UploadDate = file.Date,
UserName = file.IdUser.ToString()
}).ToList();
return fileInfoFromDb;
}
public (int Id, string Name, int IdCategory)? GetFileInfo(int fileId)
{
var fileInfo = db.Files.FirstOrDefault(f => f.Id == fileId);
if (fileInfo is null)
return null;
return (fileInfo.Id, fileInfo.Name, fileInfo.IdCategory);
}
}
}

View File

@ -0,0 +1,133 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using AsbCloudApp.Data;
using AsbCloudApp.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
namespace AsbCloudWebApi.Controllers
{
[Route("api/files")]
[ApiController]
[Authorize]
public class FileController : ControllerBase
{
private readonly IFileService fileService;
private readonly IWellService wellService;
public FileController(IFileService fileService, IWellService wellService)
{
this.fileService = fileService;
this.wellService = wellService;
}
/// <summary>
/// Сохраняет переданные файлы и информацию о них
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="idCategory">id категории файла</param>
/// <param name="idUser">id отправившего файл пользователя</param>
/// <param name="files">Коллекция файлов</param>
/// <returns></returns>
[HttpPost]
[Route("{wellId}/files")]
[ProducesResponseType(typeof(int), (int)System.Net.HttpStatusCode.OK)]
public IActionResult SaveFiles(int wellId, int idCategory, int idUser,
[FromForm] IFormFileCollection files)
{
int? idCompany = User.GetCompanyId();
if (idCompany is null)
return Forbid();
if (!wellService.CheckWellOwnership((int)idCompany, wellId))
return Forbid();
var fileInfoCollection = files.Select(f =>
(f.FileName, idCategory, DateTime.Now, idUser));
var fileNamesAndIds = fileService.SaveFilesPropertiesToDb(wellId,
idCategory, fileInfoCollection);
foreach (var file in files)
{
var fileExtension = Path.GetExtension(file.FileName);
var fileId = fileNamesAndIds[file.FileName];
var relativePath = Path.Combine(fileService.RootPath, $"{wellId}",
$"{idCategory}", $"{fileId}" + $"{fileExtension}");
Directory.CreateDirectory(Path.GetDirectoryName(relativePath));
using var fileStream = new FileStream(relativePath, FileMode.Create);
file.CopyTo(fileStream);
}
return Ok();
}
/// <summary>
/// Возвращает информацию о файлах для скважины в выбраной категории
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="idCategory">id категории файла</param>
/// <returns>Список информации о файлах в этой категории</returns>
[HttpGet]
[Route("{wellId}/filesInfo")]
[ProducesResponseType(typeof(IEnumerable<FilePropertiesDto>), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetFilesInfo([FromRoute] int wellId, int idCategory)
{
int? idCompany = User.GetCompanyId();
if (idCompany is null || !wellService.CheckWellOwnership((int)idCompany, wellId))
return Forbid();
var filesInfo = fileService.GetFilesInfo(wellId, idCategory);
if (!filesInfo.Any())
return NoContent();
return Ok(filesInfo);
}
/// <summary>
/// Возвращает файл с диска на сервере
/// </summary>
/// <param name="wellId">id скважины</param>
/// <param name="fileId">id запрашиваемого файла</param>
/// <returns>Запрашиваемый файл</returns>
[HttpGet]
[Route("{wellId}/{fileName}")]
[ProducesResponseType(typeof(PhysicalFileResult), (int)System.Net.HttpStatusCode.OK)]
public IActionResult GetFile([FromRoute] int wellId, int fileId)
{
try
{
int? idCompany = User.GetCompanyId();
if (idCompany is null)
return Forbid();
if (!wellService.CheckWellOwnership((int)idCompany, wellId))
return Forbid();
var fileInfo = fileService.GetFileInfo(fileId);
if (fileInfo is null)
throw new FileNotFoundException();
// TODO: словарь content typoв
var relativePath = Path.Combine(fileService.RootPath, $"{wellId}", $"{fileInfo.Value.IdCategory}",
$"{fileInfo.Value.Id}", Path.GetExtension($"{fileInfo.Value.Name}"));
return PhysicalFile(Path.GetFullPath(relativePath), "application/octet-stream", fileInfo.Value.Name);
}
catch (FileNotFoundException ex)
{
return NotFound($"Файл не найден. Текст ошибки: {ex.Message}");
}
}
}
}