Add PDF download functionality to editor components

Introduced the ability to download PDFs in the `SenderPdfImageEditor` component:
- Added `PdfFileName` parameter to specify the file name.
- Implemented `CanDownloadPdf` property to enable/disable downloads.
- Created `OnDownloadPdfAsync` method to handle download logic via JS interop.

Updated `SenderPdfImageEditorToolbar` to support downloads:
- Added `CanDownloadPdf` and `DownloadPdf` parameters.
- Enabled "Download PDF" button based on `CanDownloadPdf`.
- Added `DownloadPdfAsync` method to trigger the download callback.

Enhanced `SenderEditorPage` to pass `PdfFileName` to `SenderPdfImageEditor`.

Added `downloadDataUrlAsFile` function in `envelope-editor.js` to facilitate file downloads using a temporary `<a>` element.

Made minor adjustments for consistency, including adding `ZoomStepPercent` to the toolbar and refining `SetZoomPercent` logic.
This commit is contained in:
2026-09-30 16:48:51 +02:00
parent e2322b41cd
commit 021d7cfe29
4 changed files with 60 additions and 2 deletions

View File

@@ -15,6 +15,7 @@
ZoomPercent="@_zoomPercent"
MinZoomPercent="@MinZoomPercent"
MaxZoomPercent="@MaxZoomPercent"
ZoomStepPercent="@ZoomStepPercent"
GoFirstPage="OnGoFirstPageAsync"
GoPreviousPage="OnGoPreviousPageAsync"
GoNextPage="OnGoNextPageAsync"
@@ -22,7 +23,9 @@
GoToPage="OnGoToPageAsync"
ZoomOut="OnZoomOutAsync"
ZoomIn="OnZoomInAsync"
SetZoomPercent="OnSetZoomPercentAsync" />
SetZoomPercent="OnSetZoomPercentAsync"
CanDownloadPdf="@CanDownloadPdf"
DownloadPdf="OnDownloadPdfAsync" />
</div>
}
@@ -120,6 +123,9 @@
[Parameter]
public string? PdfDataUrl { get; set; }
[Parameter]
public string? PdfFileName { get; set; }
[Parameter]
public IReadOnlyList<SenderPdfFieldOverlay> Fields { get; set; } = Array.Empty<SenderPdfFieldOverlay>();
@@ -143,6 +149,7 @@
private const int MinZoomPercent = 50;
private const int MaxZoomPercent = 300;
private const int ZoomStepPercent = 5;
private bool CanDownloadPdf => !string.IsNullOrWhiteSpace(PdfDataUrl);
private static string GetFieldStyle(SenderPdfFieldOverlay field, double pageWidthPt, double pageHeightPt)
{
@@ -370,6 +377,26 @@
_zoomPercent = Math.Max(MinZoomPercent, Math.Min(value, MaxZoomPercent));
}
private async Task OnDownloadPdfAsync()
{
if (string.IsNullOrWhiteSpace(PdfDataUrl))
return;
var fallbackName = string.IsNullOrWhiteSpace(PdfFileName)
? "document.pdf"
: PdfFileName;
var fileName = fallbackName.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)
? fallbackName
: $"{fallbackName}.pdf";
await JSRuntime.InvokeVoidAsync(
"envelopeEditor.downloadDataUrlAsFile",
PdfDataUrl,
fileName,
"application/pdf");
}
private void OnEditorMouseUp(MouseEventArgs args)
{
_draggedFieldIndex = null;

View File

@@ -94,7 +94,7 @@
</svg>
</button>
<button type="button" class="sender-image-toolbar__icon-btn" title="Download PDF" disabled>
<button type="button" class="sender-image-toolbar__icon-btn" title="Download PDF" disabled="@(!CanDownloadPdf)" @onclick="DownloadPdfAsync">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 4V14" stroke="currentColor" stroke-width="2" stroke-linecap="round" />
<path d="M8 10L12 14L16 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" />
@@ -147,6 +147,12 @@
[Parameter]
public EventCallback<int> SetZoomPercent { get; set; }
[Parameter]
public bool CanDownloadPdf { get; set; }
[Parameter]
public EventCallback DownloadPdf { get; set; }
private int CurrentPageDisplay => CurrentPage > 0 ? CurrentPage : 0;
private int TotalPagesDisplay => TotalPages > 0 ? TotalPages : 0;
private int ZoomPercentDisplay => ZoomPercent > 0 ? ZoomPercent : 100;
@@ -226,4 +232,10 @@
zoomPercent = Math.Max(MinZoomPercent, Math.Min(zoomPercent, MaxZoomPercent));
await SetZoomPercent.InvokeAsync(zoomPercent);
}
private async Task DownloadPdfAsync()
{
if (DownloadPdf.HasDelegate)
await DownloadPdf.InvokeAsync();
}
}

View File

@@ -335,6 +335,7 @@
PageCount="@_pageCount"
Pages="@_pagePreviews"
PdfDataUrl="@PdfDataUrl"
PdfFileName="@_fileName"
Fields="@FieldOverlays"
EditorClick="OnPdfAreaClickAsync"
MoveField="OnMoveFieldAsync"

View File

@@ -225,5 +225,23 @@ window.envelopeEditor = {
viewer.addEventListener('touchmove', function () {
}, { passive: true });
},
downloadDataUrlAsFile: function (dataUrl, fileName, mimeType) {
if (!dataUrl || typeof dataUrl !== 'string') {
return;
}
const downloadName = fileName || 'document.pdf';
const link = document.createElement('a');
link.href = dataUrl;
link.download = downloadName;
link.rel = 'noopener';
const host = document.body || document.documentElement;
host.appendChild(link);
link.click();
host.removeChild(link);
}
};