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; /// /// Implementation of PDF operations client (merge, annotate, stamp). /// public class PdfOperationsClient(HttpClient httpClient, ILogger logger) : BaseDocumentClient(httpClient, logger), IPdfOperationsClient { // ==================== MERGE OPERATIONS ==================== /// public async Task MergeAsync(IEnumerable pdfStreams, List? 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); } /// public async Task MergeAsync(IEnumerable pdfByteArrays, List? 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 ==================== /// public async Task 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); } /// public async Task 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 ==================== /// public async Task 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); } /// public async Task StampAsync(byte[] pdfBytes, AddStampBase64Request request, CancellationToken cancellationToken = default) { var requestWithPdf = request with { Base64Pdf = ToBase64(pdfBytes) }; return await SendJsonForStreamAsync( "/api/pdf/operations/stamp", requestWithPdf, cancellationToken); } }