feat: Add specialized client implementations for PDF operations

This commit is contained in:
2026-08-11 10:29:24 +02:00
parent 14250f0b4b
commit 058cb9327d
7 changed files with 711 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
using DocumentService.Client.Interfaces;
using DocumentService.Client.Models.Requests;
using Microsoft.Extensions.Logging;
using System.Net.Http;
using System.Net.Http.Headers;
namespace DocumentService.Client.Clients;
/// <summary>
/// Implementation of PDF operations client (merge, annotate, stamp).
/// </summary>
public class PdfOperationsClient(HttpClient httpClient, ILogger<PdfOperationsClient> logger) : BaseDocumentClient(httpClient, logger), IPdfOperationsClient
{
// ==================== MERGE OPERATIONS ====================
/// <inheritdoc />
public async Task<Stream> MergeAsync(IEnumerable<Stream> pdfStreams, List<string?>? pageRanges = null, CancellationToken cancellationToken = default)
{
using var content = new MultipartFormDataContent();
foreach (var stream in pdfStreams)
{
var streamContent = new StreamContent(stream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(streamContent, "files", $"file_{Guid.NewGuid()}.pdf");
}
return await SendMultipartContentForStreamAsync("/api/pdf/operations/merge", content, cancellationToken);
}
/// <inheritdoc />
public async Task<Stream> MergeAsync(IEnumerable<byte[]> pdfByteArrays, List<string?>? pageRanges = null, CancellationToken cancellationToken = default)
{
var request = new MergePdfsBase64Request
{
Base64Pdfs = [.. pdfByteArrays.Select(ToBase64)],
PageRanges = pageRanges
};
return await SendJsonForStreamAsync(
"/api/pdf/operations/merge",
request,
cancellationToken);
}
// ==================== ANNOTATION OPERATIONS ====================
/// <inheritdoc />
public async Task<Stream> AnnotateAsync(Stream pdfStream, AddAnnotationBase64Request request, CancellationToken cancellationToken = default)
{
// For multipart, we need to send form data with all annotation parameters
using var content = new MultipartFormDataContent();
var streamContent = new StreamContent(pdfStream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(streamContent, "File", "document.pdf");
// Add annotation parameters as form fields
content.Add(new StringContent(request.AnnotationType.ToString()), "AnnotationType");
content.Add(new StringContent(request.PageNumber.ToString()), "PageNumber");
content.Add(new StringContent(request.X1.ToString()), "X1");
content.Add(new StringContent(request.Y1.ToString()), "Y1");
if (request.X2.HasValue)
content.Add(new StringContent(request.X2.Value.ToString()), "X2");
if (request.Y2.HasValue)
content.Add(new StringContent(request.Y2.Value.ToString()), "Y2");
if (request.Width.HasValue)
content.Add(new StringContent(request.Width.Value.ToString()), "Width");
if (request.Height.HasValue)
content.Add(new StringContent(request.Height.Value.ToString()), "Height");
if (!string.IsNullOrEmpty(request.Content))
content.Add(new StringContent(request.Content), "Content");
if (!string.IsNullOrEmpty(request.Author))
content.Add(new StringContent(request.Author), "Author");
if (!string.IsNullOrEmpty(request.Color))
content.Add(new StringContent(request.Color), "Color");
if (request.TextMarkupStyle.HasValue)
content.Add(new StringContent(request.TextMarkupStyle.Value.ToString()), "TextMarkupStyle");
content.Add(new StringContent(request.Origin.ToString()), "Origin");
return await SendMultipartContentForStreamAsync("/api/pdf/operations/annotate", content, cancellationToken);
}
/// <inheritdoc />
public async Task<Stream> AnnotateAsync(byte[] pdfBytes, AddAnnotationBase64Request request, CancellationToken cancellationToken = default)
{
var requestWithPdf = request with { Base64Pdf = ToBase64(pdfBytes) };
return await SendJsonForStreamAsync(
"/api/pdf/operations/annotate",
requestWithPdf,
cancellationToken);
}
// ==================== STAMP OPERATIONS ====================
/// <inheritdoc />
public async Task<Stream> StampAsync(Stream pdfStream, AddStampBase64Request request, CancellationToken cancellationToken = default)
{
// For multipart, we need to send form data with all stamp parameters
using var content = new MultipartFormDataContent();
var streamContent = new StreamContent(pdfStream);
streamContent.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
content.Add(streamContent, "File", "document.pdf");
// Add stamp parameters as form fields
content.Add(new StringContent(request.StampType.ToString()), "StampType");
content.Add(new StringContent(request.X.ToString()), "X");
content.Add(new StringContent(request.Y.ToString()), "Y");
if (request.PageNumbers != null && request.PageNumbers.Length > 0)
{
foreach (var pageNum in request.PageNumbers)
{
content.Add(new StringContent(pageNum.ToString()), "PageNumbers");
}
}
if (request.Width.HasValue)
content.Add(new StringContent(request.Width.Value.ToString()), "Width");
if (request.Height.HasValue)
content.Add(new StringContent(request.Height.Value.ToString()), "Height");
content.Add(new StringContent(request.Origin.ToString()), "Origin");
if (!string.IsNullOrEmpty(request.Text))
content.Add(new StringContent(request.Text), "Text");
if (!string.IsNullOrEmpty(request.FontName))
content.Add(new StringContent(request.FontName), "FontName");
if (request.FontSize.HasValue)
content.Add(new StringContent(request.FontSize.Value.ToString()), "FontSize");
if (!string.IsNullOrEmpty(request.Color))
content.Add(new StringContent(request.Color), "Color");
if (request.Opacity.HasValue)
content.Add(new StringContent(request.Opacity.Value.ToString()), "Opacity");
if (request.Rotation.HasValue)
content.Add(new StringContent(request.Rotation.Value.ToString()), "Rotation");
content.Add(new StringContent(request.Placement.ToString()), "Placement");
if (request.PredefinedType.HasValue)
content.Add(new StringContent(request.PredefinedType.Value.ToString()), "PredefinedType");
return await SendMultipartContentForStreamAsync("/api/pdf/operations/stamp", content, cancellationToken);
}
/// <inheritdoc />
public async Task<Stream> StampAsync(byte[] pdfBytes, AddStampBase64Request request, CancellationToken cancellationToken = default)
{
var requestWithPdf = request with { Base64Pdf = ToBase64(pdfBytes) };
return await SendJsonForStreamAsync(
"/api/pdf/operations/stamp",
requestWithPdf,
cancellationToken);
}
}