diff --git a/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQuery.cs b/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQuery.cs
index f8e5480..6cefd9b 100644
--- a/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQuery.cs
+++ b/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQuery.cs
@@ -6,19 +6,14 @@ using MediatR;
namespace DocumentOperator.Application.CheckPdfAttachments.Queries;
///
-/// Query for checking PDF attachments (supports both byte array and Base64 input)
+/// Query for checking PDF attachments (Stream-based)
///
public record CheckPdfAttachmentsQuery : IRequest
{
///
- /// PDF as byte array (direct upload via multipart/form-data)
+ /// PDF as stream (caller is responsible for disposal)
///
- public byte[]? PdfBytes { get; init; }
-
- ///
- /// PDF as Base64 string (for API clients using application/json)
- ///
- public string? Base64Pdf { get; init; }
+ public required Stream PdfStream { get; init; }
}
///
@@ -33,14 +28,8 @@ public class CheckPdfAttachmentsQueryHandler(IPdfProcessor PdfProcessor, IMapper
///
public async Task Handle(CheckPdfAttachmentsQuery request, CancellationToken cancellationToken)
{
- // Use byte[] if available, otherwise convert Base64
- byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
-
- // Convert to stream for IPdfProcessor
- using var pdfStream = new MemoryStream(pdfBytes);
-
- // Call DevExpress service (exceptions propagate naturally)
- var attachmentInfo = await PdfProcessor.CheckAttachmentsAsync(pdfStream);
+ // Call DevExpress service directly with stream (exceptions propagate naturally)
+ var attachmentInfo = await PdfProcessor.CheckAttachmentsAsync(request.PdfStream);
// Map DTO to response DTO using AutoMapper
return Mapper.Map(attachmentInfo);
diff --git a/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQueryValidator.cs b/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQueryValidator.cs
index 78aa602..a075f76 100644
--- a/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQueryValidator.cs
+++ b/DocumentOperator.Application/CheckPdfAttachments/Queries/CheckPdfAttachmentsQueryValidator.cs
@@ -4,41 +4,15 @@ namespace DocumentOperator.Application.CheckPdfAttachments.Queries;
///
/// Validator for CheckPdfAttachmentsQuery
-/// Ensures exactly one input type (PdfBytes OR Base64Pdf) is provided
+/// Ensures PdfStream is not null
///
public class CheckPdfAttachmentsQueryValidator : AbstractValidator
{
public CheckPdfAttachmentsQueryValidator()
{
- // Rule 1: Exactly ONE input must be provided (XOR logic)
- RuleFor(x => x)
- .Must(x => (x.PdfBytes != null && x.PdfBytes.Length > 0) ^
- (!string.IsNullOrWhiteSpace(x.Base64Pdf)))
- .WithMessage("Either PdfBytes or Base64Pdf must be provided, but not both");
-
- // Rule 2: Base64 format validation (if provided)
- RuleFor(x => x.Base64Pdf)
- .Must(BeValidBase64)
- .When(x => !string.IsNullOrWhiteSpace(x.Base64Pdf))
- .WithMessage("Base64Pdf must be a valid Base64 string");
- }
-
- ///
- /// Validates if a string is a valid Base64 format
- ///
- private bool BeValidBase64(string? base64)
- {
- if (string.IsNullOrWhiteSpace(base64))
- return true; // Skip validation if null/empty (handled by Rule 1)
-
- try
- {
- Convert.FromBase64String(base64);
- return true;
- }
- catch (FormatException)
- {
- return false;
- }
+ // Rule: PdfStream must be provided and non-empty
+ RuleFor(x => x.PdfStream)
+ .NotNull()
+ .WithMessage("PdfStream is required");
}
}
diff --git a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
index 8c093fa..b0992d6 100644
--- a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
+++ b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
@@ -6,19 +6,14 @@ using MediatR;
namespace DocumentOperator.Application.SwissQrCode.Queries;
///
-/// Query for extracting Swiss QR Code from PDF (supports both byte array and Base64 input)
+/// Query for extracting Swiss QR Code from PDF (Stream-based)
///
public record ExtractSwissQrCodeQuery : IRequest
{
///
- /// PDF as byte array (direct upload)
+ /// PDF as stream (caller is responsible for disposal)
///
- public byte[]? PdfBytes { get; init; }
-
- ///
- /// PDF as Base64 string (API clients)
- ///
- public string? Base64Pdf { get; init; }
+ public required Stream PdfStream { get; init; }
}
///
@@ -34,11 +29,8 @@ public class ExtractSwissQrCodeQueryHandler(ISwissQrCodeProcessor qrCodeProcesso
///
public async Task Handle(ExtractSwissQrCodeQuery request, CancellationToken cancellationToken)
{
- // Use byte[] if available, otherwise convert Base64
- byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
-
- // Extract: returns (Bill, RawLines)
- var (bill, rawLines) = await qrCodeProcessor.ExtractSwissQrCodeAsync(pdfBytes, pageNumbers: null, cancellationToken);
+ // Extract: returns (Bill, RawLines) - pass stream directly
+ var (bill, rawLines) = await qrCodeProcessor.ExtractSwissQrCodeAsync(request.PdfStream, pageNumbers: null, cancellationToken);
// Map Codecrete Bill to DTO using AutoMapper
var billDto = mapper.Map(bill);
diff --git a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQueryValidator.cs b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQueryValidator.cs
index 5e99612..f7246ee 100644
--- a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQueryValidator.cs
+++ b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQueryValidator.cs
@@ -5,55 +5,15 @@ namespace DocumentOperator.Application.SwissQrCode.Queries;
///
/// Validates ExtractSwissQrCodeQuery before handler execution.
-/// Ensures exactly ONE input method is provided (either PdfBytes OR Base64Pdf, not both, not none).
+/// Ensures PdfStream is not null.
///
public sealed class ExtractSwissQrCodeQueryValidator : AbstractValidator
{
public ExtractSwissQrCodeQueryValidator()
{
- RuleFor(x => x)
- .Must(HasExactlyOneInput)
- .WithMessage("Either PdfBytes or Base64Pdf must be provided, but not both");
-
- // Validate Base64 format if provided
- When(x => !string.IsNullOrWhiteSpace(x.Base64Pdf), () =>
- {
- RuleFor(x => x.Base64Pdf)
- .Must(BeValidBase64)
- .WithMessage("Invalid Base64 format");
- });
-
- // Validate byte array if provided
- When(x => x.PdfBytes != null, () =>
- {
- RuleFor(x => x.PdfBytes)
- .NotEmpty()
- .WithMessage("PdfBytes cannot be empty");
- });
- }
-
- private static bool HasExactlyOneInput(ExtractSwissQrCodeQuery request)
- {
- var hasPdfBytes = request.PdfBytes != null && request.PdfBytes.Length > 0;
- var hasBase64 = !string.IsNullOrWhiteSpace(request.Base64Pdf);
-
- // XOR: exactly one must be true
- return hasPdfBytes ^ hasBase64;
- }
-
- private static bool BeValidBase64(string? base64)
- {
- if (string.IsNullOrWhiteSpace(base64))
- return false;
-
- try
- {
- Convert.FromBase64String(base64);
- return true;
- }
- catch (FormatException)
- {
- return false;
- }
+ // Rule: PdfStream must be provided
+ RuleFor(x => x.PdfStream)
+ .NotNull()
+ .WithMessage("PdfStream is required");
}
}
diff --git a/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQuery.cs b/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQuery.cs
index 0f08a5c..453ebac 100644
--- a/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQuery.cs
+++ b/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQuery.cs
@@ -6,19 +6,14 @@ using MediatR;
namespace DocumentOperator.Application.ValidatePdf.Queries;
///
-/// Query for PDF validation (supports both byte array and Base64 input)
+/// Query for PDF validation (Stream-based)
///
public record ValidatePdfQuery : IRequest
{
///
- /// PDF as byte array (direct upload)
+ /// PDF as stream (caller is responsible for disposal)
///
- public byte[]? PdfBytes { get; init; }
-
- ///
- /// PDF as Base64 string (API clients)
- ///
- public string? Base64Pdf { get; init; }
+ public required Stream PdfStream { get; init; }
}
///
@@ -33,14 +28,8 @@ public class ValidatePdfQueryHandler(IPdfProcessor PdfProcessor, IMapper Mapper)
///
public async Task Handle(ValidatePdfQuery request, CancellationToken cancellationToken)
{
- // Use byte[] if available, otherwise convert Base64
- byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
-
- // Convert to stream for IPdfProcessor (using MemoryStream)
- using var pdfStream = new MemoryStream(pdfBytes);
-
- // Call DevExpress service (exceptions propagate naturally)
- var metadata = await PdfProcessor.ValidateAsync(pdfStream);
+ // Call DevExpress service directly with stream (exceptions propagate naturally)
+ var metadata = await PdfProcessor.ValidateAsync(request.PdfStream);
// Map DTO to response DTO using AutoMapper
return Mapper.Map(metadata);
diff --git a/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQueryValidator.cs b/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQueryValidator.cs
index 1e9bb5b..4a1dfa8 100644
--- a/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQueryValidator.cs
+++ b/DocumentOperator.Application/ValidatePdf/Queries/ValidatePdfQueryValidator.cs
@@ -5,55 +5,15 @@ namespace DocumentOperator.Application.ValidatePdf.Queries;
///
/// Validator for ValidatePdfQuery
-/// Ensures exactly ONE input method is provided (either PdfBytes OR Base64Pdf, not both, not none)
+/// Ensures PdfStream is not null
///
public class ValidatePdfQueryValidator : AbstractValidator
{
public ValidatePdfQueryValidator()
{
- RuleFor(x => x)
- .Must(HasExactlyOneInput)
- .WithMessage("Either PdfBytes or Base64Pdf must be provided, but not both");
-
- // Validate Base64 format if provided
- When(x => !string.IsNullOrWhiteSpace(x.Base64Pdf), () =>
- {
- RuleFor(x => x.Base64Pdf)
- .Must(BeValidBase64)
- .WithMessage("Invalid Base64 format");
- });
-
- // Validate byte array if provided
- When(x => x.PdfBytes != null, () =>
- {
- RuleFor(x => x.PdfBytes)
- .NotEmpty()
- .WithMessage("PdfBytes cannot be empty");
- });
- }
-
- private static bool HasExactlyOneInput(ValidatePdfQuery request)
- {
- var hasPdfBytes = request.PdfBytes != null && request.PdfBytes.Length > 0;
- var hasBase64 = !string.IsNullOrWhiteSpace(request.Base64Pdf);
-
- // XOR: exactly one must be true
- return hasPdfBytes ^ hasBase64;
- }
-
- private static bool BeValidBase64(string? base64)
- {
- if (string.IsNullOrWhiteSpace(base64))
- return false;
-
- try
- {
- Convert.FromBase64String(base64);
- return true;
- }
- catch (FormatException)
- {
- return false;
- }
+ // Rule: PdfStream must be provided
+ RuleFor(x => x.PdfStream)
+ .NotNull()
+ .WithMessage("PdfStream is required");
}
}
diff --git a/DocumentOperator.Application/ValidatePdfA/Queries/ValidatePdfAQuery.cs b/DocumentOperator.Application/ValidatePdfA/Queries/ValidatePdfAQuery.cs
index 64cdcca..6a23273 100644
--- a/DocumentOperator.Application/ValidatePdfA/Queries/ValidatePdfAQuery.cs
+++ b/DocumentOperator.Application/ValidatePdfA/Queries/ValidatePdfAQuery.cs
@@ -6,19 +6,14 @@ using MediatR;
namespace DocumentOperator.Application.ValidatePdfA.Queries;
///
-/// Query for PDF/A validation (supports both byte array and Base64 input)
+/// Query for PDF/A validation (Stream-based)
///
public record ValidatePdfAQuery : IRequest
{
///
- /// PDF as byte array (direct upload)
+ /// PDF as stream (caller is responsible for disposal)
///
- public byte[]? PdfBytes { get; init; }
-
- ///
- /// PDF as Base64 string (API clients)
- ///
- public string? Base64Pdf { get; init; }
+ public required Stream PdfStream { get; init; }
}
///
@@ -33,14 +28,8 @@ public class ValidatePdfAQueryHandler(IPdfProcessor PdfProcessor, IMapper Mapper
///
public async Task Handle(ValidatePdfAQuery request, CancellationToken cancellationToken)
{
- // Use byte[] if available, otherwise convert Base64
- byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
-
- // Convert to stream for IPdfProcessor
- using var pdfStream = new MemoryStream(pdfBytes);
-
- // Call DevExpress service (exceptions propagate naturally)
- var metadata = await PdfProcessor.ValidatePdfAAsync(pdfStream);
+ // Call DevExpress service directly with stream (exceptions propagate naturally)
+ var metadata = await PdfProcessor.ValidatePdfAAsync(request.PdfStream);
// Map DTO to response DTO using AutoMapper
return Mapper.Map(metadata);
diff --git a/DocumentOperator.Application/ValidatePdfA/Validators/ValidatePdfAQueryValidator.cs b/DocumentOperator.Application/ValidatePdfA/Validators/ValidatePdfAQueryValidator.cs
index 8ee807f..67277ed 100644
--- a/DocumentOperator.Application/ValidatePdfA/Validators/ValidatePdfAQueryValidator.cs
+++ b/DocumentOperator.Application/ValidatePdfA/Validators/ValidatePdfAQueryValidator.cs
@@ -4,45 +4,15 @@ namespace DocumentOperator.Application.ValidatePdfA.Validators;
///
/// Validator for ValidatePdfAQuery
-/// Ensures exactly ONE input format is provided (PdfBytes XOR Base64Pdf)
+/// Ensures PdfStream is not null
///
public class ValidatePdfAQueryValidator : AbstractValidator
{
public ValidatePdfAQueryValidator()
{
- RuleFor(x => x)
- .Must(x => (x.PdfBytes != null && x.PdfBytes.Length > 0) ^
- !string.IsNullOrWhiteSpace(x.Base64Pdf))
- .WithMessage("Either PdfBytes or Base64Pdf must be provided, but not both");
-
- When(x => !string.IsNullOrWhiteSpace(x.Base64Pdf), () =>
- {
- RuleFor(x => x.Base64Pdf!)
- .Must(BeValidBase64)
- .WithMessage("Base64Pdf must be a valid Base64 string");
- });
-
- When(x => x.PdfBytes != null, () =>
- {
- RuleFor(x => x.PdfBytes!)
- .Must(bytes => bytes.Length > 0)
- .WithMessage("PdfBytes cannot be empty");
- });
- }
-
- private static bool BeValidBase64(string base64)
- {
- if (string.IsNullOrWhiteSpace(base64))
- return false;
-
- try
- {
- Convert.FromBase64String(base64);
- return true;
- }
- catch (FormatException)
- {
- return false;
- }
+ // Rule: PdfStream must be provided
+ RuleFor(x => x.PdfStream)
+ .NotNull()
+ .WithMessage("PdfStream is required");
}
}