Updated the `ComposeSignaturePreviewPng` method in the `IPdfPageImageRenderer` interface to return a `Stream` instead of a `byte[]` for improved memory efficiency when handling large image data. - Added `ComposeSignaturePreviewPngBytes` extension method to convert the `Stream` to a `byte[]` for backward compatibility. - Updated `PdfPageImageRenderer` to return a `Stream` and adjusted its internal logic to reset the `MemoryStream` position before returning. - Modified `DevSignatureInkController` to use the `Stream`-based implementation for HTTP responses. - Made minor formatting adjustments in `PdfPageImageRenderer`. These changes optimize memory usage while maintaining compatibility with existing workflows that require `byte[]`.
100 lines
3.7 KiB
C#
100 lines
3.7 KiB
C#
using DigitalData.Core.Abstraction.Application.Repository;
|
|
using DevExpress.Drawing;
|
|
using DevExpress.Pdf;
|
|
using EnvelopeGenerator.Application.Common.Dto;
|
|
using EnvelopeGenerator.Domain.Entities;
|
|
using EnvelopeGenerator.Domain.Interfaces;
|
|
using Microsoft.AspNetCore.Authorization;
|
|
using Microsoft.AspNetCore.Mvc;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using EnvelopeGenerator.Application.Common.Interfaces.Doc;
|
|
|
|
namespace EnvelopeGenerator.Server.Controllers;
|
|
|
|
/// <summary>
|
|
/// Temporary development endpoint to download stored signature ink image by element id.
|
|
/// </summary>
|
|
[ApiController]
|
|
[AllowAnonymous]
|
|
[Route("api/dev/signature-ink")]
|
|
public class DevSignatureInkController(
|
|
IRepository<DocReceiverElement> repository,
|
|
IWebHostEnvironment environment,
|
|
IConfiguration configuration,
|
|
IPdfPageImageRenderer renderer) : ControllerBase
|
|
{
|
|
/// <summary>
|
|
/// Downloads the signature image stored in INK for the given DocumentReceiverElement id.
|
|
/// </summary>
|
|
[HttpGet("{id:int}")]
|
|
public async Task<IActionResult> DownloadInk([FromRoute] int id, CancellationToken cancel)
|
|
{
|
|
if (!IsEndpointEnabled())
|
|
return NotFound();
|
|
|
|
var element = await repository.Query
|
|
.AsNoTracking()
|
|
.Where(e => e.Id == id)
|
|
.Select(e => new DocReceiverElementDto
|
|
{
|
|
Id = e.Id,
|
|
Ink = e.Ink
|
|
})
|
|
.SingleOrDefaultAsync(cancel);
|
|
|
|
if (element is null)
|
|
return NotFound($"DocumentReceiverElement not found for id={id}.");
|
|
|
|
if (element.Ink is not { Length: > 0 })
|
|
return NotFound($"No signature image (Ink) found for id={id}.");
|
|
|
|
var image = element.ToImage();
|
|
return File(image.Bytes, image.ContentType, $"signature-ink-{id}{image.FileExtension}");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Downloads a composed signature image (background + ink + signer metadata) for the given element id.
|
|
/// </summary>
|
|
[HttpGet("{id:int}/composed")]
|
|
public async Task<IActionResult> DownloadComposedInk([FromRoute] int id, CancellationToken cancel)
|
|
{
|
|
if (!IsEndpointEnabled())
|
|
return NotFound();
|
|
|
|
var element = await repository.Query
|
|
.AsNoTracking()
|
|
.Where(e => e.Id == id)
|
|
.Select(e => new DocReceiverElementDto
|
|
{
|
|
Id = e.Id,
|
|
Ink = e.Ink,
|
|
FullName = e.FullName,
|
|
Position = e.Position,
|
|
Place = e.Place,
|
|
ChangedWhen = e.ChangedWhen
|
|
})
|
|
.SingleOrDefaultAsync(cancel);
|
|
|
|
if (element is null)
|
|
return NotFound($"DocumentReceiverElement not found for id={id}.");
|
|
|
|
if (element.Ink is not { Length: > 0 })
|
|
return NotFound($"No signature image (Ink) found for id={id}.");
|
|
|
|
if (element.ChangedWhen is null)
|
|
return Conflict($"DocumentReceiverElement id={id} has null ChangedWhen. Element is not signed yet or data integrity is broken.");
|
|
|
|
if (string.IsNullOrWhiteSpace(element.FullName) || string.IsNullOrWhiteSpace(element.Place))
|
|
return Conflict($"DocumentReceiverElement id={id} is missing signer metadata (FullName or Place).");
|
|
|
|
if (!renderer.IsSupportedImageFormat(element.Ink!))
|
|
return StatusCode(StatusCodes.Status415UnsupportedMediaType);
|
|
|
|
var composedStream = renderer.ComposeSignaturePreviewPng(element);
|
|
return File(composedStream, "image/png", $"signature-composed-{id}.png");
|
|
}
|
|
|
|
private bool IsEndpointEnabled()
|
|
=> environment.IsDevelopment() || configuration.GetValue<bool>("DevEndpoints:EnableSignatureInkInProduction");
|
|
}
|