This commit is contained in:
Hamid Reza Mohammadi 2023-07-22 20:18:33 +03:30
commit 713dd63533
6 changed files with 578 additions and 14 deletions

View File

@ -0,0 +1,237 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using RMuseum.Models.Artifact;
using RMuseum.Models.Auth.Memory;
using RMuseum.Models.PDFLibrary;
using RMuseum.Models.PDFLibrary.ViewModels;
using RMuseum.Services;
using RSecurityBackend.Models.Auth.Memory;
using RSecurityBackend.Models.Generic;
using System.Linq;
using System;
using System.Net;
using System.Threading.Tasks;
using RSecurityBackend.Services;
namespace RMuseum.Controllers
{
[Produces("application/json")]
[Route("api/pdf")]
public class PDFLibraryController : Controller
{
/// <summary>
/// start importing a local pdf file
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
[HttpPost]
[Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK)]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public IActionResult StartImportingLocalPDF([FromBody] NewPDFBookViewModel model)
{
var res = _pdfService.StartImportingLocalPDF(model);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok();
}
/// <summary>
/// secure get a pdf book
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("secure/{id}")]
[Authorize]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PDFBook))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task<IActionResult> GetUserVisible(int id)
{
RServiceResult<PublishStatus[]> v = await _GetUserVisibleArtifactStatusSet
(
new Guid(User.Claims.FirstOrDefault(c => c.Type == "UserId").Value),
new Guid(User.Claims.FirstOrDefault(c => c.Type == "SessionId").Value)
);
if (!string.IsNullOrEmpty(v.ExceptionString))
return BadRequest(v.ExceptionString);
PublishStatus[] visibleItems = v.Result;
RServiceResult<PDFBook> bookRes = null;
if (visibleItems.Length == 1 && visibleItems[0] == PublishStatus.Published)
{
bookRes = await _pdfService.GetPDFBookByIdAsync(id, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(bookRes.ExceptionString))
{
return BadRequest(bookRes.ExceptionString);
}
if (bookRes.Result == null)
return NotFound();
}
if (bookRes == null)
{
bookRes = await _pdfService.GetPDFBookByIdAsync(id, visibleItems);
}
if (!string.IsNullOrEmpty(bookRes.ExceptionString))
{
return BadRequest(bookRes.ExceptionString);
}
if (bookRes.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = bookRes.Result.LastModified;
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= bookRes.Result.LastModified)
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(bookRes.Result);
}
private async Task<RServiceResult<PublishStatus[]>> _GetUserVisibleArtifactStatusSet(Guid loggedOnUserId, Guid sessionId)
{
RServiceResult<bool>
canView =
await _userPermissionChecker.Check
(
loggedOnUserId,
sessionId,
RMuseumSecurableItem.PDFLibraryEntityShortName,
RMuseumSecurableItem.ViewDraftOperationShortName
);
if (!string.IsNullOrEmpty(canView.ExceptionString))
return new RServiceResult<PublishStatus[]>(null, canView.ExceptionString);
PublishStatus[] visibleItems =
canView.Result
?
new PublishStatus[]
{
PublishStatus.Published,
PublishStatus.Restricted,
PublishStatus.Draft,
PublishStatus.Awaiting
}
:
new PublishStatus[]
{
PublishStatus.Published
};
return new RServiceResult<PublishStatus[]>(visibleItems);
}
/// <summary>
/// get published PDF Book by id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
[HttpGet("{id}")]
[AllowAnonymous]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(PDFBook))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
[ProducesResponseType((int)HttpStatusCode.NotFound)]
public async Task<IActionResult> GetPDFBookByIdAsync(int id)
{
var bookRes = await _pdfService.GetPDFBookByIdAsync(id, new PublishStatus[] { PublishStatus.Published });
if (!string.IsNullOrEmpty(bookRes.ExceptionString))
{
return BadRequest(bookRes.ExceptionString);
}
if (bookRes.Result == null)
return NotFound();
Response.GetTypedHeaders().LastModified = bookRes.Result.LastModified;
var requestHeaders = Request.GetTypedHeaders();
if (requestHeaders.IfModifiedSince.HasValue &&
requestHeaders.IfModifiedSince.Value >= bookRes.Result.LastModified)
{
return StatusCode(StatusCodes.Status304NotModified);
}
return Ok(bookRes.Result);
}
/// <summary>
/// add a new book
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
[HttpPost("book")]
[Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Book))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task<IActionResult> AddBookAsync([FromBody] Book book)
{
var res = await _pdfService.AddBookAsync(book);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
/// <summary>
/// add a new author
/// </summary>
/// <param name="author"></param>
/// <returns></returns>
[HttpPost("author")]
[Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(Author))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task<IActionResult> AddAuthorAsync([FromBody] Author author)
{
var res = await _pdfService.AddAuthorAsync(author);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
/// <summary>
/// add a new mukti volume pdf collection
/// </summary>
/// <param name="volumes"></param>
/// <returns></returns>
[HttpPost("volumes")]
[Authorize(Policy = RMuseumSecurableItem.PDFLibraryEntityShortName + ":" + SecurableItem.ModifyOperationShortName)]
[ProducesResponseType((int)HttpStatusCode.OK, Type = typeof(MultiVolumePDFCollection))]
[ProducesResponseType((int)HttpStatusCode.BadRequest, Type = typeof(string))]
public async Task<IActionResult> AddMultiVolumePDFCollection([FromBody] MultiVolumePDFCollection volumes)
{
var res = await _pdfService.AddMultiVolumePDFCollection(volumes);
if (!string.IsNullOrEmpty(res.ExceptionString))
return BadRequest(res.ExceptionString);
return Ok(res.Result);
}
/// <summary>
/// PDF Service
/// </summary>
protected readonly IPDFLibraryService _pdfService;
/// <summary>
/// IUserPermissionChecker instance
/// </summary>
protected IUserPermissionChecker _userPermissionChecker;
/// <summary>
/// constructor
/// </summary>
/// <param name="pdfService"></param>
/// <param name="userPermissionChecker"></param>
public PDFLibraryController(IPDFLibraryService pdfService, IUserPermissionChecker userPermissionChecker)
{
_pdfService = pdfService;
_userPermissionChecker = userPermissionChecker;
}
}
}

View File

@ -108,6 +108,11 @@ namespace RMuseum.Models.Auth.Memory
/// </summary>
public const string ModeratePoetPhotos = "photos";
/// <summary>
/// pdf
/// </summary>
public const string PDFLibraryEntityShortName = "pdf";
/// <summary>
/// list of forms and their permissions
/// </summary>
@ -194,6 +199,16 @@ namespace RMuseum.Models.Auth.Memory
new SecurableItemOperation(ModerateOperationShortName, "مدیریت", false),
}
},
new SecurableItem()
{
ShortName = PDFLibraryEntityShortName,
Description = "نسک‌بان",
Operations = new SecurableItemOperation[]
{
new SecurableItemOperation(ModifyOperationShortName, "ویرایش محتوا", false),
new SecurableItemOperation(ViewDraftOperationShortName, "مشاهدهٔ پیش‌نویس‌ها", false),
}
},

View File

@ -2343,6 +2343,65 @@
<param name="numberingService"></param>
<param name="configuration"></param>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.StartImportingLocalPDF(RMuseum.Models.PDFLibrary.ViewModels.NewPDFBookViewModel)">
<summary>
start importing a local pdf file
</summary>
<param name="model"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.GetUserVisible(System.Int32)">
<summary>
secure get a pdf book
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.GetPDFBookByIdAsync(System.Int32)">
<summary>
get published PDF Book by id
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.AddBookAsync(RMuseum.Models.PDFLibrary.Book)">
<summary>
add a new book
</summary>
<param name="book"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.AddAuthorAsync(RMuseum.Models.PDFLibrary.Author)">
<summary>
add a new author
</summary>
<param name="author"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.AddMultiVolumePDFCollection(RMuseum.Models.PDFLibrary.MultiVolumePDFCollection)">
<summary>
add a new mukti volume pdf collection
</summary>
<param name="volumes"></param>
<returns></returns>
</member>
<member name="F:RMuseum.Controllers.PDFLibraryController._pdfService">
<summary>
PDF Service
</summary>
</member>
<member name="F:RMuseum.Controllers.PDFLibraryController._userPermissionChecker">
<summary>
IUserPermissionChecker instance
</summary>
</member>
<member name="M:RMuseum.Controllers.PDFLibraryController.#ctor(RMuseum.Services.IPDFLibraryService,RSecurityBackend.Services.IUserPermissionChecker)">
<summary>
constructor
</summary>
<param name="pdfService"></param>
<param name="userPermissionChecker"></param>
</member>
<member name="M:RMuseum.Controllers.RecitationController.GetPublished(RSecurityBackend.Models.Generic.PagingParameterModel,System.String,System.Int32,System.Int32)">
<summary>
returns paginated published recitations (if poetId or catId is non-zero its ordered by poemId ascending if not it is ordered by publish date descending)
@ -4387,6 +4446,11 @@
photos
</summary>
</member>
<member name="F:RMuseum.Models.Auth.Memory.RMuseumSecurableItem.PDFLibraryEntityShortName">
<summary>
pdf
</summary>
</member>
<member name="P:RMuseum.Models.Auth.Memory.RMuseumSecurableItem.Items">
<summary>
list of forms and their permissions
@ -17424,6 +17488,14 @@
طول تصویر بندانگشتی
</summary>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.GetPDFBookByIdAsync(System.Int32,RMuseum.Models.Artifact.PublishStatus[])">
<summary>
get pdf book by id
</summary>
<param name="id"></param>
<param name="statusArray"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.StartImportingLocalPDF(RMuseum.Models.PDFLibrary.ViewModels.NewPDFBookViewModel)">
<summary>
start importing local pdf file
@ -17431,6 +17503,42 @@
<param name="model"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.AddAuthorAsync(RMuseum.Models.PDFLibrary.Author)">
<summary>
add author
</summary>
<param name="author"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.GetAuthorByIdAsync(System.Int32)">
<summary>
get author by id
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.GetAuthorsAsync(RSecurityBackend.Models.Generic.PagingParameterModel,System.String)">
<summary>
get authors
</summary>
<param name="paging"></param>
<param name="authorName"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.AddBookAsync(RMuseum.Models.PDFLibrary.Book)">
<summary>
add book
</summary>
<param name="book"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.Implementation.PDFLibraryService.AddMultiVolumePDFCollection(RMuseum.Models.PDFLibrary.MultiVolumePDFCollection)">
<summary>
add multi volume pdf collection
</summary>
<param name="multiVolumePDFCollection"></param>
<returns></returns>
</member>
<member name="F:RMuseum.Services.Implementation.PDFLibraryService._context">
<summary>
Database Context
@ -18234,6 +18342,50 @@
PDF Library Services
</summary>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.GetPDFBookByIdAsync(System.Int32,RMuseum.Models.Artifact.PublishStatus[])">
<summary>
get pdf book by id
</summary>
<param name="id"></param>
<param name="statusArray"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.AddAuthorAsync(RMuseum.Models.PDFLibrary.Author)">
<summary>
add author
</summary>
<param name="author"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.GetAuthorByIdAsync(System.Int32)">
<summary>
get author by id
</summary>
<param name="id"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.GetAuthorsAsync(RSecurityBackend.Models.Generic.PagingParameterModel,System.String)">
<summary>
get authors
</summary>
<param name="paging"></param>
<param name="authorName"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.AddBookAsync(RMuseum.Models.PDFLibrary.Book)">
<summary>
add book
</summary>
<param name="book"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.AddMultiVolumePDFCollection(RMuseum.Models.PDFLibrary.MultiVolumePDFCollection)">
<summary>
add multi volume pdf collection
</summary>
<param name="multiVolumePDFCollection"></param>
<returns></returns>
</member>
<member name="M:RMuseum.Services.IPDFLibraryService.StartImportingLocalPDF(RMuseum.Models.PDFLibrary.ViewModels.NewPDFBookViewModel)">
<summary>
start importing local pdf file

View File

@ -1,5 +1,8 @@
using RMuseum.Models.PDFLibrary.ViewModels;
using RMuseum.Models.Artifact;
using RMuseum.Models.PDFLibrary;
using RMuseum.Models.PDFLibrary.ViewModels;
using RSecurityBackend.Models.Generic;
using System.Threading.Tasks;
namespace RMuseum.Services
{
@ -8,6 +11,50 @@ namespace RMuseum.Services
/// </summary>
public interface IPDFLibraryService
{
/// <summary>
/// get pdf book by id
/// </summary>
/// <param name="id"></param>
/// <param name="statusArray"></param>
/// <returns></returns>
Task<RServiceResult<PDFBook>> GetPDFBookByIdAsync(int id, PublishStatus[] statusArray);
/// <summary>
/// add author
/// </summary>
/// <param name="author"></param>
/// <returns></returns>
Task<RServiceResult<Author>> AddAuthorAsync(Author author);
/// <summary>
/// get author by id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
Task<RServiceResult<Author>> GetAuthorByIdAsync(int id);
/// <summary>
/// get authors
/// </summary>
/// <param name="paging"></param>
/// <param name="authorName"></param>
/// <returns></returns>
Task<RServiceResult<(PaginationMetadata PagingMeta, Author[] Authors)>> GetAuthorsAsync(PagingParameterModel paging, string authorName);
/// <summary>
/// add book
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
Task<RServiceResult<Book>> AddBookAsync(Book book);
/// <summary>
/// add multi volume pdf collection
/// </summary>
/// <param name="multiVolumePDFCollection"></param>
/// <returns></returns>
Task<RServiceResult<MultiVolumePDFCollection>> AddMultiVolumePDFCollection(MultiVolumePDFCollection multiVolumePDFCollection);
/// <summary>
/// start importing local pdf file
/// </summary>

View File

@ -20,7 +20,7 @@ namespace RMuseum.Services.Implementation
{
public partial class PDFLibraryService
{
private async Task<RServiceResult<PDFBook>> ImportLocalPDFFile(RMuseumDbContext context, int bookId, int? volumeId, int volumeOrder, string filePath, string srcUrl, bool skipUpload)
private async Task<RServiceResult<PDFBook>> ImportLocalPDFFileAsync(RMuseumDbContext context, int bookId, int? volumeId, int volumeOrder, string filePath, string srcUrl, bool skipUpload)
{
string fileChecksum = PoemAudio.ComputeCheckSum(filePath);
if (

View File

@ -1,12 +1,16 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using RMuseum.DbContext;
using RMuseum.Models.Artifact;
using RMuseum.Models.PDFLibrary;
using RMuseum.Models.PDFLibrary.ViewModels;
using RSecurityBackend.Models.Generic;
using RSecurityBackend.Services;
using RSecurityBackend.Services.Implementation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace RMuseum.Services.Implementation
{
@ -15,6 +19,32 @@ namespace RMuseum.Services.Implementation
/// </summary>
public partial class PDFLibraryService : IPDFLibraryService
{
/// <summary>
/// get pdf book by id
/// </summary>
/// <param name="id"></param>
/// <param name="statusArray"></param>
/// <returns></returns>
public async Task<RServiceResult<PDFBook>> GetPDFBookByIdAsync(int id, PublishStatus[] statusArray)
{
try
{
var pdfBook = await _context.PDFBooks.AsNoTracking()
.Include(b => b.Book)
.Include(b => b.MultiVolumePDFCollection)
.Include(b => b.Contributers)
.Include(b => b.Tags)
.Include(b => b.Pages)
.Where(b => statusArray.Contains(b.Status) &&b.Id == id)
.SingleOrDefaultAsync();
return new RServiceResult<PDFBook>(pdfBook);
}
catch (Exception exp)
{
return new RServiceResult<PDFBook>(null, exp.ToString());
}
}
/// <summary>
/// start importing local pdf file
@ -29,7 +59,7 @@ namespace RMuseum.Services.Implementation
{
using (RMuseumDbContext context = new RMuseumDbContext(new DbContextOptions<RMuseumDbContext>()))
{
var pdfRes = await ImportLocalPDFFile(context, model.BookId, model.MultiVolumePDFCollectionId, model.VolumeOrder, model.LocalImportingPDFFilePath, model.OriginalSourceUrl, model.SkipUpload);
var pdfRes = await ImportLocalPDFFileAsync(context, model.BookId, model.MultiVolumePDFCollectionId, model.VolumeOrder, model.LocalImportingPDFFilePath, model.OriginalSourceUrl, model.SkipUpload);
if (pdfRes.Result != null)
{
var pdfBook = pdfRes.Result;
@ -49,7 +79,7 @@ namespace RMuseum.Services.Implementation
pdfBook.OriginalSourceName = model.OriginalSourceName;
pdfBook.OriginalFileUrl = model.OriginalFileUrl;
List<AuthorRole> roles = new List<AuthorRole>();
if(model.WriterId != null)
if (model.WriterId != null)
{
roles.Add(new AuthorRole()
{
@ -81,7 +111,7 @@ namespace RMuseum.Services.Implementation
Role = "نویسنده",
});
}
if(model.TranslatorId != null)
if (model.TranslatorId != null)
{
roles.Add(new AuthorRole()
{
@ -129,7 +159,7 @@ namespace RMuseum.Services.Implementation
Role = "مصحح",
});
}
if(roles.Count > 0)
if (roles.Count > 0)
{
pdfBook.Contributers = roles;
}
@ -137,35 +167,118 @@ namespace RMuseum.Services.Implementation
await context.SaveChangesAsync();
}
}
}
);
return new RServiceResult<bool>(true);
}
/// <summary>
/// add author
/// </summary>
/// <param name="author"></param>
/// <returns></returns>
public async Task<RServiceResult<Author>> AddAuthorAsync(Author author)
{
try
{
_context.Add(author);
await _context.SaveChangesAsync();
return new RServiceResult<Author>(author);
}
catch (Exception exp)
{
return new RServiceResult<Author>(null, exp.ToString());
}
}
/// <summary>
/// get author by id
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public async Task<RServiceResult<Author>> GetAuthorByIdAsync(int id)
{
try
{
return new RServiceResult<Author>(await _context.Authors.AsNoTracking().Where(a => a.Id == id).SingleOrDefaultAsync());
}
catch (Exception exp)
{
return new RServiceResult<Author>(null, exp.ToString());
}
}
/// <summary>
/// get authors
/// </summary>
/// <param name="paging"></param>
/// <param name="authorName"></param>
/// <returns></returns>
public async Task<RServiceResult<(PaginationMetadata PagingMeta, Author[] Authors)>> GetAuthorsAsync(PagingParameterModel paging, string authorName)
{
var source =
_context.Authors
.Where(a => string.IsNullOrEmpty(authorName) || (authorName.Contains(a.Name) || (!string.IsNullOrEmpty(a.NameInOriginalLanguage) && authorName.Contains(a.NameInOriginalLanguage)) ))
.AsQueryable();
(PaginationMetadata PagingMeta, Author[] Items) paginatedResult =
await QueryablePaginator<Author>.Paginate(source, paging);
return new RServiceResult<(PaginationMetadata PagingMeta, Author[] Authors)>(paginatedResult);
}
/// <summary>
/// add book
/// </summary>
/// <param name="book"></param>
/// <returns></returns>
public async Task<RServiceResult<Book>> AddBookAsync(Book book)
{
try
{
_context.Add(book);
await _context.SaveChangesAsync();
return new RServiceResult<Book>(book);
}
catch (Exception exp)
{
return new RServiceResult<Book>(null, exp.ToString());
}
}
/// <summary>
/// add multi volume pdf collection
/// </summary>
/// <param name="multiVolumePDFCollection"></param>
/// <returns></returns>
public async Task<RServiceResult<MultiVolumePDFCollection>> AddMultiVolumePDFCollection(MultiVolumePDFCollection multiVolumePDFCollection)
{
try
{
_context.Add(multiVolumePDFCollection);
await _context.SaveChangesAsync();
return new RServiceResult<MultiVolumePDFCollection>(multiVolumePDFCollection);
}
catch (Exception exp)
{
return new RServiceResult<MultiVolumePDFCollection>(null, exp.ToString());
}
}
/// <summary>
/// Database Context
/// </summary>
protected readonly RMuseumDbContext _context;
/// <summary>
/// Background Task Queue Instance
/// </summary>
protected readonly IBackgroundTaskQueue _backgroundTaskQueue;
/// <summary>
/// image file service
/// </summary>
protected readonly IImageFileService _imageFileService;
/// <summary>
/// Configuration
/// </summary>
protected IConfiguration Configuration { get; }
/// <summary>
/// constructor
/// </summary>