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<UserRole> UserRoles { get; set; }
|
||||||
public virtual DbSet<Well> Wells { get; set; }
|
public virtual DbSet<Well> Wells { get; set; }
|
||||||
public virtual DbSet<Report> Reports { 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<Operation> Operations { get; set; }
|
||||||
public virtual DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }
|
public virtual DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }
|
||||||
public virtual DbSet<WellSection> SectionAnalysis { get; set; }
|
public virtual DbSet<WellSection> SectionAnalysis { get; set; }
|
||||||
@ -209,6 +211,24 @@ namespace AsbCloudDb.Model
|
|||||||
new Operation {Id = 17, Name = "На поверхности" }
|
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)
|
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 =>
|
modelBuilder.Entity<Telemetry>(entity =>
|
||||||
{
|
{
|
||||||
entity.HasData(new List<Telemetry>{
|
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 => {
|
modelBuilder.Entity<RelationCompanyWell>(entity => {
|
||||||
entity.HasData(new List<RelationCompanyWell> {
|
entity.HasData(new List<RelationCompanyWell> {
|
||||||
new RelationCompanyWell{ IdWell = 1, IdCompany = 1},
|
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<Well> Wells { get; set; }
|
||||||
DbSet<UserRole> UserRoles { get; set; }
|
DbSet<UserRole> UserRoles { get; set; }
|
||||||
DbSet<Report> Reports { get; set; }
|
DbSet<Report> Reports { get; set; }
|
||||||
|
DbSet<File> Files { get; set; }
|
||||||
|
DbSet<FileCategory> FileCategories { get; set; }
|
||||||
DbSet<Operation> Operations { get; set; }
|
DbSet<Operation> Operations { get; set; }
|
||||||
DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }
|
DbSet<TelemetryAnalysis> TelemetryAnalysis { get; set; }
|
||||||
|
|
||||||
|
@ -37,6 +37,7 @@ namespace AsbCloudInfrastructure
|
|||||||
services.AddTransient<ITelemetryUserService, TelemetryUserService>();
|
services.AddTransient<ITelemetryUserService, TelemetryUserService>();
|
||||||
services.AddTransient<IReportService, ReportService>();
|
services.AddTransient<IReportService, ReportService>();
|
||||||
services.AddTransient<IAnalyticsService, AnalyticsService>();
|
services.AddTransient<IAnalyticsService, AnalyticsService>();
|
||||||
|
services.AddTransient<IFileService, FileService>();
|
||||||
|
|
||||||
return services;
|
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