forked from ddrilling/AsbCloudServer
CS2-38: Добавлены модель, контроллер и сервис для сохранения и отправки файлов по категориям
This commit is contained in:
parent
1d69ddf4e5
commit
99242f6995
13
AsbCloudApp/Data/FilePropertiesDto.cs
Normal file
13
AsbCloudApp/Data/FilePropertiesDto.cs
Normal 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; }
|
||||
}
|
||||
}
|
18
AsbCloudApp/Services/IFileService.cs
Normal file
18
AsbCloudApp/Services/IFileService.cs
Normal 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);
|
||||
}
|
||||
}
|
@ -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
30
AsbCloudDb/Model/File.cs
Normal 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; }
|
||||
}
|
||||
}
|
17
AsbCloudDb/Model/FileCategory.cs
Normal file
17
AsbCloudDb/Model/FileCategory.cs
Normal 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; }
|
||||
}
|
||||
}
|
@ -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; }
|
||||
|
||||
|
@ -37,6 +37,7 @@ namespace AsbCloudInfrastructure
|
||||
services.AddTransient<ITelemetryUserService, TelemetryUserService>();
|
||||
services.AddTransient<IReportService, ReportService>();
|
||||
services.AddTransient<IAnalyticsService, AnalyticsService>();
|
||||
services.AddTransient<IFileService, FileService>();
|
||||
|
||||
return services;
|
||||
}
|
||||
|
69
AsbCloudInfrastructure/Services/FileService.cs
Normal file
69
AsbCloudInfrastructure/Services/FileService.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
133
AsbCloudWebApi/Controllers/FileController.cs
Normal file
133
AsbCloudWebApi/Controllers/FileController.cs
Normal 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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user