put in new ui and backend store image to table

This commit is contained in:
2026-09-20 14:32:59 +10:00
parent 75b49be476
commit 3d83e95613
13 changed files with 194 additions and 55 deletions
@@ -3,6 +3,7 @@ using FamilyTreeAPI.Repository;
namespace FamilyTreeAPI.Controllers; namespace FamilyTreeAPI.Controllers;
using DocumentFormat.OpenXml.Drawing.Charts;
using FamilyTreeAPI.Interface; using FamilyTreeAPI.Interface;
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives; using Microsoft.Extensions.Primitives;
@@ -115,9 +116,30 @@ public class FileUploadController : ControllerBase
public async Task<IActionResult> DownloadPersonPhoto(DownloadFileCriteria criteria) public async Task<IActionResult> DownloadPersonPhoto(DownloadFileCriteria criteria)
{ {
var result = await _personPhoto.DownloadPersonPhoto(criteria.Id, criteria.FileName); var result = await _personPhoto.DownloadPersonPhoto(criteria.Id,criteria.PhotoType ,criteria.FileName);
if (result.StatusCode > 0)
return File(result.Data.Content, result.Data.ContentType, result.Data.FileName); return File(result.Data.Content, result.Data.ContentType, result.Data.FileName);
else
return NotFound("not found image");
}
[HttpPost("[action]")]
public async Task<IActionResult> DownloadPersonPhoto64(DownloadFileCriteria criteria)
{
var result = await _personPhoto.DownloadPersonPhoto(criteria.Id,criteria.PhotoType ,criteria.FileName);
if (result.StatusCode > 0)
{
byte[] file64 = result.Data.Content;
string rval = Convert.ToBase64String(file64);
ResultModel<string> retval = new() {
Data = rval,
StatusCode = 1,
Message = ""
};
return Ok(retval);
}
else
return NotFound("not found image");
} }
[HttpPost("[action]")] [HttpPost("[action]")]
public async Task<ActionResult> DeletePersonPhoto(DeleteFileCriteria criteria) public async Task<ActionResult> DeletePersonPhoto(DeleteFileCriteria criteria)
@@ -127,8 +149,18 @@ public class FileUploadController : ControllerBase
if ( criteria.Id > 0) if ( criteria.Id > 0)
{ {
ret = await _personPhoto.DeletePersonPhoto(criteria.Id); ret = await _personPhoto.DeletePersonPhoto(criteria.Id, criteria.PhotoType);
} }
return Ok(ret); return Ok(ret);
} }
[HttpPost("[action]")]
public async Task<ActionResult> DeletePersonPhotoById(DeleteCriteria<int> criteria)
{
ResultModel<int> ret = new();
ret = await _personPhoto.DeletePersonPhotoById(criteria.Id);
return Ok(ret);
}
} }
@@ -14,6 +14,7 @@ namespace FamilyTreeAPI.Controllers
{ {
_repo = repo; _repo = repo;
} }
[HttpPost("[action]")] [HttpPost("[action]")]
public async Task<IActionResult> UploadImage(IFormFile file) public async Task<IActionResult> UploadImage(IFormFile file)
{ {
+4 -1
View File
@@ -15,16 +15,19 @@ public class DownloadFileCriteria
{ {
public string FileName { get; set; } public string FileName { get; set; }
public int Id { get; set; } public int Id { get; set; }
public int PhotoType {get; set;}
} }
public class UploadCriteria public class UploadCriteria
{ {
public string FileName { get; set; } public string FileName { get; set; }
public int PersonId { get; set; } public int PersonId { get; set; }
public int? PhotoType {get; set;} public int PhotoType {get; set;}
public IFormFile File { get; set; } public IFormFile File { get; set; }
} }
public class DeleteFileCriteria public class DeleteFileCriteria
{ {
public int Id { get; set; } public int Id { get; set; }
public string Filename { get; set; } public string Filename { get; set; }
public int PhotoType {get; set;}
} }
+6
View File
@@ -2,6 +2,12 @@
{ {
public class Helpers public class Helpers
{ {
public static string GetFileExtension(string fileName)
{
string result = System.IO.Path.GetExtension(fileName);
return result;
}
public static string GetFileContent(string extension) public static string GetFileContent(string extension)
{ {
string contentType = ""; string contentType = "";
+3 -2
View File
@@ -5,8 +5,9 @@ namespace FamilyTreeAPI.Interface;
public interface IPersonPhoto public interface IPersonPhoto
{ {
Task<ResultModel<int>> SaveAsync(UploadCriteria criteria); Task<ResultModel<int>> SaveAsync(UploadCriteria criteria);
Task<ResultModel<FileContent>> DownloadPersonPhoto(int id, string? filename); Task<ResultModel<FileContent>> DownloadPersonPhoto(int id, int photoType, string filename);
Task<ResultModel<int>> DeletePersonPhoto(int id); Task<ResultModel<int>> DeletePersonPhoto(int id, int photoType);
Task<ResultModel<int>> DeletePersonPhotoById(int id);
Task<ResultModel<List<PersonPhotoDto>>> LoadPersonPhoto(int personId); Task<ResultModel<List<PersonPhotoDto>>> LoadPersonPhoto(int personId);
} }
@@ -3,6 +3,7 @@ using FamilyTreeAPI.Entities;
using FamilyTreeAPI.Helper; using FamilyTreeAPI.Helper;
using FamilyTreeAPI.Interface; using FamilyTreeAPI.Interface;
using FamilyTreeAPI.Models; using FamilyTreeAPI.Models;
using HotChocolate.CostAnalysis.Types;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
namespace FamilyTreeAPI.Repository namespace FamilyTreeAPI.Repository
@@ -31,12 +32,12 @@ namespace FamilyTreeAPI.Repository
dto.PhotoType = model.PhotoType; dto.PhotoType = model.PhotoType;
return dto; return dto;
} }
private PersonPhoto FillModel(PersonPhoto model, int personId, string filename) private PersonPhoto FillModel(PersonPhoto model, int personId, int photoType, string filename)
{ {
model.PersonId = personId; model.PersonId = personId;
model.Photo = filename; model.Photo = filename;
model.PhotoType = System.IO.Path.GetExtension(filename); model.PhotoType = photoType.ToString(); //System.IO.Path.GetExtension(filename);
return model; return model;
} }
@@ -46,8 +47,8 @@ namespace FamilyTreeAPI.Repository
int statuscode = 0; int statuscode = 0;
string error = "";//Other string error = "";//Other
string photoType = "2"; // string photoType = "2"; //
if (criteria.PhotoType.HasValue) if (criteria.PhotoType > 0)
photoType = criteria.PhotoType.Value.ToString(); photoType = criteria.PhotoType.ToString();
HttpContext? httpContext = _httpContext.HttpContext; HttpContext? httpContext = _httpContext.HttpContext;
string loginName = ""; string loginName = "";
if (httpContext != null) if (httpContext != null)
@@ -64,8 +65,8 @@ namespace FamilyTreeAPI.Repository
PersonPhoto model; PersonPhoto model;
model = new(); model = new();
model.PhotoType = photoType;
model = FillModel(model,criteria.PersonId, formfile.FileName); model = FillModel(model,criteria.PersonId, criteria.PhotoType,formfile.FileName);
using (var stream = new MemoryStream()) using (var stream = new MemoryStream())
{ {
@@ -93,14 +94,15 @@ namespace FamilyTreeAPI.Repository
}; };
} }
public async Task<ResultModel<FileContent>> DownloadPersonPhoto(int id, string? filename) public async Task<ResultModel<FileContent>> DownloadPersonPhoto(int personId, int photoType, string filename)
{ {
int statusCode = -1; int statusCode = -1;
string error = ""; string error = "";
string extension = "";
PersonPhoto? model = null; PersonPhoto? model = null;
FileContent fileContent = new(); FileContent fileContent = new();
if (id < 1) if (personId < 1)
{ {
var rlist = await _context.PersonPhotos.Where(x => x.Photo == filename).ToListAsync(); var rlist = await _context.PersonPhotos.Where(x => x.Photo == filename).ToListAsync();
if (rlist != null) if (rlist != null)
@@ -111,19 +113,26 @@ namespace FamilyTreeAPI.Repository
} }
} }
} }
else else
{ {
model = await _context.PersonPhotos.FindAsync(id); var rlist = await _context.PersonPhotos.Where (x => x.PersonId == personId && photoType.ToString() == x.PhotoType).ToListAsync();
for ( int i = 0; i < rlist.Count; i++)
{
model = rlist[i];
break;
}
} }
if (model != null) if (model != null)
{ {
fileContent.ContentType = Helpers.GetFileContent(model.PhotoType); extension = Helpers.GetFileExtension(model.Photo);
fileContent.ContentType = Helpers.GetFileContent(extension);
fileContent.Content = (byte[])model.ImagePhoto; fileContent.Content = (byte[])model.ImagePhoto;
fileContent.FileName = model.Photo; fileContent.FileName = model.Photo;
statusCode = 1; statusCode = 1;
} }
return new ResultModel<FileContent>() return new ResultModel<FileContent>()
{ {
Data = fileContent, Data = fileContent,
@@ -132,21 +141,70 @@ namespace FamilyTreeAPI.Repository
}; };
} }
public async Task<ResultModel<int>> DeletePersonPhoto(int id) public async Task<ResultModel<int>> DeletePersonPhoto(int personId, int photoType)
{ {
int result = default(int); int result = default(int);
int statuscode = 0; int statuscode = 0;
string error = ""; string error = "";
PersonPhoto? model;
try try
{ {
PersonPhoto? model = await _context.PersonPhotos.FindAsync(id); if (photoType < 1)
if (model != null)
{ {
List<PersonPhoto> list = await _context.PersonPhotos.Where ( x => x.PersonId == personId).ToListAsync();
for (int i = 0; i< list.Count; i++)
{
model = list[i];
_context.PersonPhotos.Remove(model); _context.PersonPhotos.Remove(model);
await _context.SaveChangesAsync(); await _context.SaveChangesAsync();
statuscode = 1; statuscode = 1;
} }
} }
else
{
List<PersonPhoto> list = await _context.PersonPhotos.Where ( x => x.PersonId == personId && x.PhotoType == photoType.ToString()).ToListAsync();
for (int i = 0; i< list.Count; i++)
{
model = list[i];
_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<int>> DeletePersonPhotoById(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) catch (Exception ex)
{ {
error = ex.ToString(); error = ex.ToString();
@@ -283,7 +283,7 @@ public partial class PersonRepository : IPerson
node.Key = item.Id.ToString(); node.Key = item.Id.ToString();
node.Type = type; node.Type = type;
if (item.Image != null) if (item.Image != null)
node.Data.Image = await LoadPersonImage(item.Id,item.Image); node.Data.Image = await LoadPersonImage(item.Id, (int) enumPhotoType.Profile, item.Image);
node.Icon = "T"; node.Icon = "T";
node.StyleClass = getStyleClass(node.Icon); node.StyleClass = getStyleClass(node.Icon);
@@ -392,7 +392,7 @@ public partial class PersonRepository : IPerson
citem.Data = new(); citem.Data = new();
citem.Label = pName; citem.Label = pName;
if (image != null) if (image != null)
citem.Data.Image = await LoadPersonImage(personId,image); citem.Data.Image = await LoadPersonImage(personId, (int) enumPhotoType.Profile, image);
citem.Icon = "P"; citem.Icon = "P";
@@ -413,7 +413,7 @@ public partial class PersonRepository : IPerson
child.Type = type; child.Type = type;
image = dto.Image; image = dto.Image;
if (image != null) if (image != null)
child.Data.Image = await LoadPersonImage(dto.Id,image); child.Data.Image = await LoadPersonImage(dto.Id,(int) enumPhotoType.Profile, image);
child.Icon = "C"; child.Icon = "C";
child.StyleClass = getStyleClass(child.Icon); child.StyleClass = getStyleClass(child.Icon);
child.Label = dto.FirstName; child.Label = dto.FirstName;
@@ -750,13 +750,13 @@ public partial class PersonRepository : IPerson
return result; return result;
} }
private async Task<string> LoadPersonImage(int personId,string filename) private async Task<string> LoadPersonImage(int personId, int photoType, string filename)
{ {
string result = ""; string result = "";
// DownloadFileCriteria criteria = new() { FileName = filename }; // DownloadFileCriteria criteria = new() { FileName = filename };
var resultModel = await _personPhoto.DownloadPersonPhoto(personId, filename); var resultModel = await _personPhoto.DownloadPersonPhoto(personId, photoType , filename);
//if (resultModel.Data.Content) //if (resultModel.Data.Content)
string base64String = Convert.ToBase64String(resultModel.Data.Content); string base64String = Convert.ToBase64String(resultModel.Data.Content);
+2 -1
View File
@@ -16,7 +16,7 @@
<th>Id</th> <th>Id</th>
<th pSortableColumn="description">Description<p-sortIcon field="description"></p-sortIcon> <th pSortableColumn="description">Description<p-sortIcon field="description"></p-sortIcon>
</th> </th>
<th>Photo Type</th>
<th>Action</th> <th>Action</th>
</tr> </tr>
@@ -25,6 +25,7 @@
<tr> <tr>
<td>{{item.id}}</td> <td>{{item.id}}</td>
<td >{{item.photo}}</td> <td >{{item.photo}}</td>
<td>{{item.photoType}}</td>
<td> <td>
<button pButton type="button" icon="pi pi-times" <button pButton type="button" icon="pi pi-times"
+1 -1
View File
@@ -128,7 +128,7 @@ doRemove(id: number): void {
} }
else else
{ {
const deletepersonPhoto$ = this.personService.deletePersonPhotoFile(id); const deletepersonPhoto$ = this.personService.deletePersonPhotoFileById(id);
this.subscription.add(deletepersonPhoto$.subscribe( this.subscription.add(deletepersonPhoto$.subscribe(
{ {
next: x => { next: x => {
+4 -1
View File
@@ -15,7 +15,10 @@ export enum mState {
Modified = 1, Modified = 1,
New =2, New =2,
}; };
export enum enumPhoto {
Profile = 1,
Other = 2
}
export enum userRole { export enum userRole {
Normal = 1, Normal = 1,
Admin = 2, Admin = 2,
+12 -7
View File
@@ -6,7 +6,7 @@ import { FormControl, ReactiveFormsModule, UntypedFormBuilder, Validators } from
import { Subject, Subscription} from 'rxjs'; import { Subject, Subscription} from 'rxjs';
import { ConfirmationService, MessageService } from 'primeng/api'; import { ConfirmationService, MessageService } from 'primeng/api';
import { DatePickerModule } from 'primeng/datepicker'; import { DatePickerModule } from 'primeng/datepicker';
import { Code, RelationShipView, Person, mState, RelationShip, PersonPhotoDto} from '../models'; import { Code, RelationShipView, Person, mState, RelationShip, PersonPhotoDto, enumPhoto } from '../models';
import { AppSettingService, LookupService, Utils } from '../shares'; import { AppSettingService, LookupService, Utils } from '../shares';
import { PersonService } from './person.service'; import { PersonService } from './person.service';
import { ButtonModule } from 'primeng/button'; import { ButtonModule } from 'primeng/button';
@@ -22,6 +22,7 @@ import { TooltipModule } from 'primeng/tooltip';
import { AutoFocusModule } from 'primeng/autofocus'; import { AutoFocusModule } from 'primeng/autofocus';
import { DomSanitizer } from '@angular/platform-browser'; import { DomSanitizer } from '@angular/platform-browser';
import { PhotoList } from '../attachphoto/photolist'; import { PhotoList } from '../attachphoto/photolist';
import { InputNumberDesignTokens } from '@primeuix/themes/types/inputnumber';
export interface FileUploadEvent { export interface FileUploadEvent {
originalEvent: HttpEvent<any>; originalEvent: HttpEvent<any>;
@@ -190,9 +191,9 @@ doDeleteFile(): void {
this.profileFile = null; this.profileFile = null;
} }
doDeleteImage(fileName:string) : void { doDeleteImage(fileName:string) : void {
const familyId = this.adminuserForm.value.id; const personId = this.adminuserForm.value.id;
const data = { fileName, familyId }; const photoType = enumPhoto.Profile;
const delete$ = this.personService.deleteUploadFile(data); const delete$ = this.personService.deletePersonPhotoFile(personId, photoType);
this.subscription.add(delete$.subscribe( this.subscription.add(delete$.subscribe(
{ {
next: x => { next: x => {
@@ -358,7 +359,7 @@ assignValue(item:Person): void {
} }
if (item.image && item.image.length > 0) if (item.image && item.image.length > 0)
{ {
this.loadImage(item.image); this.loadImage(item.image, item.id, enumPhoto.Profile);
} }
// disable use false//true for not disable. // disable use false//true for not disable.
this.subChanged$.next(true); this.subChanged$.next(true);
@@ -367,8 +368,10 @@ assignValue(item:Person): void {
// convenience getter for easy access in form fields // convenience getter for easy access in form fields
get f() { return this.adminuserForm.controls;} get f() { return this.adminuserForm.controls;}
loadImage(fileName: string| null): void { loadImage(fileName: string | null,
const download = this.personService.downloadFile(fileName!); personId: number, photoType: number): void {
if (fileName) {
const download = this.personService.downloadPersonPhoto64(fileName, personId, photoType);
this.subscription.add(download.subscribe({ this.subscription.add(download.subscribe({
next: x => { next: x => {
if (x.statusCode == 1) if (x.statusCode == 1)
@@ -385,6 +388,8 @@ assignValue(item:Person): void {
error: e => console.error("error in download image", e) error: e => console.error("error in download image", e)
})); }));
} }
}
displayIamge64(baseImage: string): void displayIamge64(baseImage: string): void
{ {
const changeUrl = (this.sanitizer.bypassSecurityTrustResourceUrl(baseImage) as any).changingThisBreaksApplicationSecurity; const changeUrl = (this.sanitizer.bypassSecurityTrustResourceUrl(baseImage) as any).changingThisBreaksApplicationSecurity;
+36 -9
View File
@@ -77,33 +77,60 @@ export class PersonService {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/UploadImage"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/UploadImage";
return this.http.post<ResultModel<string>>(baseUrl, data); return this.http.post<ResultModel<string>>(baseUrl, data);
} }
downloadFile(imageName: string): Observable<ResultModel<string>> { downloadFile_dontusethis(imageName: string, personId: number,
photoType: number): Observable<ResultModel<string>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadFile"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadFile";
const data = { const data = {
fileName: imageName fileName: imageName,
id: personId,
photoType
}; };
return this.http.post<ResultModel<string>>(baseUrl, data); return this.http.post<ResultModel<string>>(baseUrl, data);
} }
deleteUploadFile(data: any): Observable<ResultModel<number>> { deleteUploadFile_dotnotuse(data: any): Observable<ResultModel<number>> {
//data ={filename}; //data ={filename};
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.personUrl + "/DeleteUploadFile";
return this.http.post<ResultModel<number>>(baseUrl, data); return this.http.post<ResultModel<number>>(baseUrl, data);
} }
deletePersonPhotoFile(id: number): Observable<ResultModel<number>> { deletePersonPhotoFile(personId: number, photoType: number): Observable<ResultModel<number>> {
const data ={id, fileName:''}; const data = {
id: personId,
fileName: '',
photoType
};
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DeletePersonPhoto"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DeletePersonPhoto";
return this.http.post<ResultModel<number>>(baseUrl, data); return this.http.post<ResultModel<number>>(baseUrl, data);
} }
deletePersonPhotoFileById(id: number): Observable<ResultModel<number>> {
const data = {
id
};
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DeletePersonPhotoById";
return this.http.post<ResultModel<number>>(baseUrl, data);
}
savePersonPhotoList(data:FormData): Observable<ResultModel<number>> { savePersonPhotoList(data:FormData): Observable<ResultModel<number>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/SavePersonPhoto"; const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/SavePersonPhoto";
return this.http.post<ResultModel<number>>(baseUrl, data); return this.http.post<ResultModel<number>>(baseUrl, data);
} }
downloadPersonPhoto(id: number): Observable<ResultModel<string>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadPersonPhoto"; downloadPersonPhoto64(imageName: string, personId: number,
photoType: number): Observable<ResultModel<string>> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadPersonPhoto64";
const data = { const data = {
id, id: personId,
fileName: '' photoType,
fileName: imageName
}; };
return this.http.post<ResultModel<string>>(baseUrl, data); return this.http.post<ResultModel<string>>(baseUrl, data);
} }
downloadPersonPhoto(imageName: string, personId: number,
photoType: number): Observable<any> {
const baseUrl = this.appSetting.appSetting.baseUrl + "/" + ConfigureUrl.FileUploadUrl + "/DownloadPersonPhoto";
const data = {
id: personId,
photoType,
fileName: imageName
};
return this.http.post<any>(baseUrl, data);
}
} }
+5 -3
View File
@@ -28,11 +28,13 @@ export class ImageDisplayComponent implements OnInit, OnDestroy {
ngOnInit(): void { ngOnInit(): void {
const imageName = this.config.data.imageName; const imageName = this.config.data.imageName;
this.loadImage(imageName); const personId = this.config.data.personId;
const photoType = this.config.data.photyType;
this.loadImage(imageName, personId, photoType);
} }
loadImage(fileName: string| null): void { loadImage(fileName: string | null, personId: number, photoType: number): void {
const download = this.personService.downloadFile(fileName!); const download = this.personService.downloadPersonPhoto(fileName!, personId, photoType);
this.subscription.add(download.subscribe({ this.subscription.add(download.subscribe({
next: x => { next: x => {
if (x.statusCode == 1) if (x.statusCode == 1)