Add PDF attachment and PDF/A conversion features
Introduced endpoints for embedding attachments in PDFs and converting between standard PDFs and PDF/A formats. Added `PdfAttachmentController` and `PdfConversionController` with multipart/form-data and Base64-based support. Implemented commands, handlers, and validators for these operations. Extended `IPdfProcessor` with methods for adding attachments and PDF/A conversion. Partially implemented functionality in `DevExpressPdfProcessor`, including `ConvertFromPdfAAsync`. Added `attachment.xml` and `withoutAttachment.pdf` as resources for testing. Marked endpoints as `[Obsolete]` to indicate incomplete implementation. Improved validation and error handling for commands.
This commit is contained in:
@@ -1093,4 +1093,113 @@ public class DevExpressPdfProcessor : IPdfProcessor
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Add Attachments (Phase 2)
|
||||
|
||||
/// <summary>
|
||||
/// Embeds one or more files as attachments in a PDF document (supports PDF/A-3).
|
||||
/// </summary>
|
||||
public async Task<byte[]> AddAttachmentsAsync(
|
||||
Stream pdfStream,
|
||||
IReadOnlyList<(string FileName, byte[] Content, string? MimeType)> attachments)
|
||||
{
|
||||
// 1. Validate input
|
||||
ArgumentNullException.ThrowIfNull(pdfStream, nameof(pdfStream));
|
||||
ArgumentNullException.ThrowIfNull(attachments, nameof(attachments));
|
||||
|
||||
if (pdfStream.Length == 0)
|
||||
throw new BadRequestException("PDF stream cannot be empty");
|
||||
|
||||
if (pdfStream.Position != 0)
|
||||
throw new BadRequestException("PDF stream must be at position 0");
|
||||
|
||||
if (attachments.Count == 0)
|
||||
throw new BadRequestException("At least one attachment is required");
|
||||
|
||||
// TODO: Implement AddFileAttachment using DevExpress.Pdf low-level API
|
||||
// Current limitation: DevExpress.Pdf.PdfDocumentProcessor doesn't directly support adding attachments
|
||||
// Workaround options:
|
||||
// 1. Use PdfDocumentProcessor.Document to manipulate PDF structure directly (advanced)
|
||||
// 2. Use third-party library for this specific operation
|
||||
// 3. Wait for DevExpress API update
|
||||
|
||||
throw new NotImplementedException(
|
||||
"Add attachments feature is not yet implemented. " +
|
||||
"DevExpress.Pdf high-level API doesn't directly support adding file attachments. " +
|
||||
"This requires low-level PDF structure manipulation.");
|
||||
}
|
||||
|
||||
private string InferMimeType(string fileName)
|
||||
{
|
||||
string extension = Path.GetExtension(fileName).ToLowerInvariant();
|
||||
return extension switch
|
||||
{
|
||||
".xml" => "application/xml",
|
||||
".pdf" => "application/pdf",
|
||||
".json" => "application/json",
|
||||
".txt" => "text/plain",
|
||||
".jpg" or ".jpeg" => "image/jpeg",
|
||||
".png" => "image/png",
|
||||
_ => "application/octet-stream"
|
||||
};
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region PDF Conversion (Phase 3)
|
||||
|
||||
/// <summary>
|
||||
/// Converts a standard PDF to PDF/A format.
|
||||
/// </summary>
|
||||
public async Task<byte[]> ConvertToPdfAAsync(Stream pdfStream, string pdfALevel)
|
||||
{
|
||||
// 1. Validate input
|
||||
ArgumentNullException.ThrowIfNull(pdfStream, nameof(pdfStream));
|
||||
|
||||
if (pdfStream.Length == 0)
|
||||
throw new BadRequestException("PDF stream cannot be empty");
|
||||
|
||||
if (pdfStream.Position != 0)
|
||||
throw new BadRequestException("PDF stream must be at position 0");
|
||||
|
||||
if (string.IsNullOrWhiteSpace(pdfALevel))
|
||||
throw new BadRequestException("PDF/A level is required");
|
||||
|
||||
// TODO: Implement PDF to PDF/A conversion using DevExpress
|
||||
// Current limitation: DevExpress.Pdf.PdfDocumentProcessor doesn't directly support PDF/A conversion
|
||||
// Requires using specialized PDF/A conversion libraries or low-level PDF manipulation
|
||||
|
||||
throw new NotImplementedException(
|
||||
$"PDF to PDF/A conversion ({pdfALevel}) is not yet implemented. " +
|
||||
"DevExpress.Pdf high-level API doesn't directly support PDF/A conversion. " +
|
||||
"This requires specialized PDF/A conversion logic.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a PDF/A document to a standard PDF (removes PDF/A restrictions).
|
||||
/// </summary>
|
||||
public async Task<byte[]> ConvertFromPdfAAsync(Stream pdfStream)
|
||||
{
|
||||
// 1. Validate input
|
||||
ArgumentNullException.ThrowIfNull(pdfStream, nameof(pdfStream));
|
||||
|
||||
if (pdfStream.Length == 0)
|
||||
throw new BadRequestException("PDF stream cannot be empty");
|
||||
|
||||
if (pdfStream.Position != 0)
|
||||
throw new BadRequestException("PDF stream must be at position 0");
|
||||
|
||||
// 2. Load PDF/A
|
||||
using var processor = new PdfDocumentProcessor();
|
||||
processor.LoadDocument(pdfStream);
|
||||
|
||||
// 3. Save as standard PDF
|
||||
// DevExpress SaveDocument without special options creates standard PDF
|
||||
using var outputStream = new MemoryStream();
|
||||
processor.SaveDocument(outputStream);
|
||||
|
||||
return await Task.FromResult(outputStream.ToArray());
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user