check add person photo finish

This commit is contained in:
2025-10-27 16:23:06 +11:00
parent c62ae2cd42
commit cbb61b796f
28 changed files with 1084 additions and 86 deletions
@@ -3,8 +3,9 @@ using FamilyTreeAPI.Repository;
namespace FamilyTreeAPI.Controllers;
using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using System.IO;
using System.Threading.Tasks;
@@ -15,11 +16,15 @@ public class FileUploadController : ControllerBase
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly ImportPersonRepository _importPersonRepository;
private readonly IConfiguration _config;
public FileUploadController(IWebHostEnvironment hostingEnvironment, ImportPersonRepository importPersonRepository, IConfiguration config)
private readonly IPersonPhoto _personPhoto;
public FileUploadController(IWebHostEnvironment hostingEnvironment,
IPersonPhoto personPhoto,
ImportPersonRepository importPersonRepository, IConfiguration config)
{
_hostingEnvironment = hostingEnvironment;
_importPersonRepository = importPersonRepository;
_config = config;
_personPhoto = personPhoto;
}
[HttpPost("[action]")]
@@ -79,4 +84,51 @@ public class FileUploadController : ControllerBase
var rev = await _importPersonRepository.DownloadFile(criteria);
return Ok(rev);
}
[HttpPost("[action]")]
public async Task<IActionResult> SavePersonPhoto(List<IFormFile> files)
{
var keys = Request.Form;
var ffiles = Request.Form.Files;
ResultModel<int> ret = new();
if (files.Count > 0)
{
StringValues sdocCId = "";
keys.TryGetValue("personId", out sdocCId);
for (int i = 0; i < files.Count; i++)
{
var file = files[i];
UploadCriteria criteria = new();
criteria.File = file;
criteria.PersonId = int.Parse(sdocCId);
criteria.FileName = file.FileName;
ret = await _personPhoto.SaveAsync(criteria);
}
}
return Ok(ret);
}
[HttpPost("[action]")]
public async Task<IActionResult> DownloadPersonPhoto(DownloadFileCriteria criteria)
{
var result = await _personPhoto.DownloadPersonPhoto(criteria.Id, criteria.FileName);
return File(result.Data.Content, result.Data.ContentType, result.Data.FileName);
}
[HttpPost("[action]")]
public async Task<ActionResult> DeletePersonPhoto(DeleteFileCriteria criteria)
{
ResultModel<int> ret = new();
if ( criteria.Id > 0)
{
ret = await _personPhoto.DeletePersonPhoto(criteria.Id);
}
return Ok(ret);
}
}
@@ -24,11 +24,11 @@ namespace FamilyTreeAPI.Controllers
{
StringValues familyId = "";
keys.TryGetValue("familyId", out familyId);
keys.TryGetValue("personId", out familyId);
UploadCriteria criteria = new();
criteria.File = file;
criteria.FamilyId = familyId;
criteria.PersonId = int.Parse(familyId);
criteria.FileName = file.FileName;
+4 -2
View File
@@ -9,20 +9,22 @@ public class FileContent
{
public byte[] Content { get; set; }
public string FileName { get; set; }
public string ContentType { get; set; }
}
public class DownloadFileCriteria
{
public string FileName { get; set; }
public int Id { get; set; }
}
public class UploadCriteria
{
public string FileName { get; set; }
public string FamilyId { get; set; }
public int PersonId { get; set; }
public IFormFile File { get; set; }
}
public class DeleteFileCriteria
{
public int FamilyId { get; set; }
public int Id { get; set; }
public string Filename { get; set; }
}
+1
View File
@@ -49,5 +49,6 @@ public partial class PersonDto
public int? MotherId { get; set; }
public List<RelationShipDto>? RelationShips { get; set; }
public List<PersonPhotoDto>? PersonPhotos { get; set; }
}
@@ -0,0 +1,10 @@
namespace FamilyTreeAPI.Entities;
public class PersonPhotoDto
{
public int Id { get; set; }
public int PersonId { get; set; }
public string Photo { get; set; }
public string? PhotoType { get; set; }
}
+74
View File
@@ -2,6 +2,80 @@
{
public class Helpers
{
public static string GetFileContent(string extension)
{
string contentType = "";
/*
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types
*/
switch (extension)
{
case ".pdf":
contentType = "application/pdf";
break;
case ".txt":
contentType = "text/plain";
break;
case ".xlsx":
contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
break;
case ".xls":
contentType = "application/vnd.ms-excel";
break;
case ".doc":
contentType = "application/msword";
break;
case ".odt":
contentType = "application/vnd.oasis.opendocument.text";
break;
case ".docx":
contentType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
break;
case ".gif":
contentType = "image/gif";
break;
case ".ppt":
contentType = "application/vnd.ms-powerpoint";
break;
case ".ico":
contentType = "image/vnd.microsoft.icon";
break;
case ".png":
contentType = "image/png";
break;
case ".rar":
contentType = "application/vnd.rar";
break;
case ".zip":
contentType = "application/zip";
break;
case ".tar":
contentType = "application/x-tar";
break;
case ".mp4":
contentType = "video/mp4";
break;
case ".jpeg":
case ".jpg":
contentType = "image/jpeg";
break;
case ".3gp":
contentType = "video/3gpp";
break;
case ".7z":
contentType = "application/x-7z-compressed";
break;
case ".tif":
case ".tiff":
contentType = "image/tiff";
break;
// and so on
// default:
// throw new ArgumentOutOfRangeException($"Unable to find Content Type for file name {file.NameWithExtension}.");
}
return contentType;
}
public static string? DateToStr(DateTime? date)
{
string? result = null;
@@ -0,0 +1,12 @@
using FamilyTreeAPI.Entities;
namespace FamilyTreeAPI.Interface;
public interface IPersonPhoto
{
Task<ResultModel<int>> SaveAsync(UploadCriteria criteria);
Task<ResultModel<FileContent>> DownloadPersonPhoto(int id, string? filename);
Task<ResultModel<int>> DeletePersonPhoto(int id);
Task<ResultModel<List<PersonPhotoDto>>> LoadPersonPhoto(int personId);
}
@@ -80,7 +80,11 @@ namespace FamilyTreeAPI.Models
entity.Property(e => e.Id).HasColumnName("id");
entity.Property(e => e.PersonId).HasColumnName("personid");
entity.Property(e => e.Photo).HasColumnName("photo");
entity.Property(e => e.Photo)
.HasColumnName("photo");
entity.Property(e => e.PhotoType)
.HasMaxLength(20)
.HasColumnName("phototype");
entity.Property(e => e.ImagePhoto).HasColumnName("imagephot"); //try to store binary in table. "bytea"
});
+1
View File
@@ -6,6 +6,7 @@
public int PersonId { get; set; }
public string Photo { get; set; }
public string? PhotoType { get; set; }
public byte[] ImagePhoto { get; set; }
+1 -1
View File
@@ -71,7 +71,7 @@ services.AddGraphQLServer()
services.AddScoped<ILookup, LookupRepository>();
services.AddScoped<IStaff, StaffRepository>();
services.AddScoped<IPersonPhoto, PersonPhotoRepository>();
services.AddScoped<IRelationShipd,RelationShipRepository>();
services.AddScoped<IPerson, PersonRepository>();
services.AddScoped<IUserService, UserServiceRepository>();
@@ -0,0 +1,197 @@
using DocumentFormat.OpenXml.Office2010.Excel;
using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Helper;
using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models;
using Microsoft.EntityFrameworkCore;
namespace FamilyTreeAPI.Repository
{
public class PersonPhotoRepository: IPersonPhoto
{
private readonly FamilyTreeDBContext _context;
private readonly IHttpContextAccessor _httpContext;
private readonly IConfiguration _config;
public PersonPhotoRepository(IConfiguration config,
FamilyTreeDBContext context,
IRelationShipd relationship,
IHttpContextAccessor httpContext)
{
_context = context;
_config = config;
_httpContext = httpContext;
}
private PersonPhotoDto FillDto(PersonPhoto model)
{
PersonPhotoDto dto = new();
dto.Id = model.Id;
dto.PersonId = model.PersonId;
dto.Photo = model.Photo;
dto.PhotoType = model.PhotoType;
return dto;
}
private PersonPhoto FillModel(PersonPhoto model, int personId, string filename)
{
model.PersonId = personId;
model.Photo = filename;
model.PhotoType = System.IO.Path.GetExtension(filename);
return model;
}
public async Task<ResultModel<int>> SaveAsync(UploadCriteria criteria)
{
int result = default(int);
int statuscode = 0;
string error = "";
HttpContext? httpContext = _httpContext.HttpContext;
string loginName = "";
if (httpContext != null)
{
UserDto? user = (UserDto?)httpContext.Items["User"];
if (user != null)
loginName = user.FirstName + " " + user.LastName;
}
try
{
IFormFile formfile = criteria.File;
PersonPhoto model;
model = new();
model = FillModel(model,criteria.PersonId, formfile.FileName);
using (var stream = new MemoryStream())
{
await formfile.CopyToAsync(stream);
model.ImagePhoto = stream.ToArray();
}
_context.PersonPhotos.Add(model);
await _context.SaveChangesAsync();
statuscode = 1;
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<FileContent>> DownloadPersonPhoto(int id, string? filename)
{
int statusCode = -1;
string error = "";
PersonPhoto? model = null;
FileContent fileContent = new();
if (id < 1)
{
var rlist = await _context.PersonPhotos.Where(x => x.Photo == filename).ToListAsync();
if (rlist != null)
{
if (rlist.Count > 0)
{
model = rlist[0];
}
}
}
else
{
model = await _context.PersonPhotos.FindAsync(id);
}
if (model != null)
{
fileContent.ContentType = Helpers.GetFileContent(model.PhotoType);
fileContent.Content = (byte[])model.ImagePhoto;
fileContent.FileName = model.Photo;
statusCode = 1;
}
return new ResultModel<FileContent>()
{
Data = fileContent,
StatusCode = statusCode,
Message = error
};
}
public async Task<ResultModel<int>> DeletePersonPhoto(int id)
{
int result = default(int);
int statuscode = 0;
string error = "";
try
{
PersonPhoto? model = await _context.PersonPhotos.FindAsync(id);
if (model != null)
{
_context.PersonPhotos.Remove(model);
await _context.SaveChangesAsync();
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
//var dto = await Task.Run(() => result);
return new ResultModel<int>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
public async Task<ResultModel<List<PersonPhotoDto>>> LoadPersonPhoto(int personId)
{
List<PersonPhotoDto> result = new();
int statuscode = 0;
string error = "";
PersonPhotoDto dto;
PersonPhoto? model;
try
{
List<PersonPhoto?> mlist = await _context.PersonPhotos.Where( x => x.PersonId == personId ).ToListAsync();
for (int i = 0; i< mlist.Count; i++)
{
model = mlist[i];
if (model != null)
{
dto = FillDto(model);
result.Add(dto);
}
statuscode = 1;
}
}
catch (Exception ex)
{
error = ex.ToString();
statuscode = -1;
}
return new ResultModel<List<PersonPhotoDto>>()
{
Data = result,
StatusCode = statuscode,
Message = error
};
}
}
}
@@ -20,12 +20,15 @@ public partial class PersonRepository : IPerson
private readonly FamilyTreeDBContext _context;
private readonly IRelationShipd _relationship;
private readonly IHttpContextAccessor _httpContext;
private readonly IPersonPhoto _personPhoto;
private readonly IConfiguration _config;
const string dateFormat = "yyyy-MM-dd";
public PersonRepository(IConfiguration config, FamilyTreeDBContext context,
IRelationShipd relationship,
IPersonPhoto personPhoto,
IHttpContextAccessor httpContext)
{
_personPhoto = personPhoto;
_context = context;
_relationship = relationship;
_config = config;
@@ -410,6 +413,8 @@ public partial class PersonRepository : IPerson
statuscode = 1;
ResultModel<List<RelationShipDto>> rlist = await _relationship.GetByPersonIdAsync(dto.Id);
dto.RelationShips = rlist.Data;
ResultModel<List<PersonPhotoDto>> personPhoto = await _personPhoto.LoadPersonPhoto(id);
dto.PersonPhotos = personPhoto.Data;
statuscode = rlist.StatusCode;
error = rlist.Message;
}
@@ -626,7 +631,7 @@ public partial class PersonRepository : IPerson
Directory.CreateDirectory(path);
}
extention = System.IO.Path.GetExtension(criteria.FileName);
filename = criteria.FamilyId + "_" + sdate + extention;
filename = criteria.PersonId + "_" + sdate + extention;
using (var fileStream = new FileStream(System.IO.Path.Combine(path, filename), FileMode.Create))
{
@@ -670,7 +675,7 @@ public partial class PersonRepository : IPerson
result = 1;
statusCode = 1;
Person? model = _context.Persons.Find(criteria.FamilyId);
Person? model = _context.Persons.Find(criteria.Id);
if (model != null)
{
model.Image = null;