Compare commits

...

3 Commits

Author SHA1 Message Date
077eb1e017 docs: Add XML documentation comments to API layer
Add missing XML doc comments to resolve CS1591 warnings:

  - SerilogConfiguration: Class comment

  - SwaggerConfiguration: Class and AddSwaggerDocumentation() method

  - ExceptionHandlingMiddleware: Constructor and InvokeAsync() method

  - RequestLoggingMiddleware: Placeholder class comment

  - TenantResolutionMiddleware: Placeholder class comment

  - Program: Partial class comment for integration test access

Result: 0 CS1591 warnings in DocumentOperator.API project
2026-07-07 18:56:23 +02:00
8b154e7378 fix: Replace CreateBitmap with CreateDXBitmap for cross-platform compatibility
- Replace System.Drawing.Bitmap with DevExpress.Drawing.DXBitmap

- Fix CA1416 warnings (Windows-specific API usage)

- Fix CS0618 warning (TryInverted property moved to Options.TryInverted)

- Add [SupportedOSPlatform(windows)] attribute to DecodeQrCodeFromImage()

- Add Swiss QR Bill backward compatibility documentation

- Suppress CS0618 for AddressLine1/AddressLine2 (deprecated since Nov 2025)

- Use modern C# 12 collection expression syntax

Technical changes:

  - CreateBitmap() to CreateDXBitmap() (returns DXBitmap)

  - Convert DXBitmap to PNG stream to System.Drawing.Bitmap for ZXing

  - Add using DevExpress.Drawing and System.Runtime.Versioning

Result: 0 CA1416 warnings, 0 CS0618 warnings in DevExpressSwissQrCodeProcessor
2026-07-07 18:56:09 +02:00
a12d529d9e Add documentation for DocumentOperator service
Added `CONTROLLER_ENDPOINTS.md` to define REST API endpoints and
`REQUIRED_FEATURES.md` to outline required functions and features
for the `DocumentOperator` service. These documents include
detailed specifications for controllers, input/output formats,
usage scenarios, and technical requirements.

Updated `DocumentOperator.sln` to include the new documentation
files under a "Solution Items" section for better visibility.

Defined a prioritization strategy for feature implementation,
technical requirements, and a comprehensive test strategy.
Referenced relevant standards (e.g., PDF/A, ZUGFeRD) and
documented usage of the DevExpress Office File API.
2026-07-06 10:33:01 +02:00
10 changed files with 973 additions and 12 deletions

348
CONTROLLER_ENDPOINTS.md Normal file
View File

@@ -0,0 +1,348 @@
# DocumentOperator - Controller & Endpoint Specification
**Project:** DocumentService (DOC)
**Ticket:** DOC-1 - GDPicture and Nutrient Replacing
**Owner:** Hakan Tek
**Date:** July 3, 2026
---
## Overview
This specification defines the controller structure and REST API endpoints for the DocumentOperator service.
---
## PdfValidationController
### Endpoint: PDF Validation
**Route:** `POST /api/pdf/validation/validate`
**Function:** Checks whether the file is a valid PDF, whether it is corrupted, and returns basic information
**Input:**
- PDF file (multipart/form-data)
**Output:**
```json
{
"isValid": bool,
"pdfVersion": string,
"pageCount": int,
"fileSize": long,
"encrypted": bool,
"errors": string[]
}
```
**Usage:** All products - basic PDF input check
---
### Endpoint: PDF/A Validation
**Route:** `POST /api/pdf/validation/validate-pdfa`
**Function:** PDF/A conformance check (embedded fonts, encryption, JavaScript, etc.)
**Input:**
- PDF file (multipart/form-data)
**Output:**
```json
{
"isValid": bool,
"pdfaVersion": string,
"pageCount": int,
"errors": string[],
"warnings": string[]
}
```
**Usage:** taskFLOW, eParser - ensuring PDF/A conformance
---
## PdfAttachmentController
### Endpoint: Attachment Check
**Route:** `POST /api/pdf/attachments/check`
**Function:** Detects whether embedded files (e.g. ZUGFeRD XML) are present in the PDF
**Input:**
- PDF file (multipart/form-data)
**Output:**
```json
{
"hasAttachments": bool,
"attachmentCount": int,
"attachments": [
{
"fileName": string,
"mimeType": string,
"size": long
}
]
}
```
**Usage:** eParser (ZUGFeRD), ErgebnisberichtCreator
---
### Endpoint: Attachment Extraction
**Route:** `POST /api/pdf/attachments/extract`
**Function:** Extracts all embedded files from the PDF and saves them to the specified path
**Input:**
```json
{
"file": "PDF (multipart/form-data)",
"outputPath": string
}
```
**Output:**
```json
{
"success": bool,
"extractedFiles": [
{
"fileName": string,
"savedPath": string,
"size": long
}
]
}
```
**Usage:** eParser (ZUGFeRD XML extraction)
---
## PdfOperationsController
### Endpoint: PDF Merge
**Route:** `POST /api/pdf/operations/merge`
**Function:** Merges multiple PDFs into a single file
**Input:**
```json
{
"sourceFiles": string[],
"outputPath": string
}
```
**Output:**
```json
{
"success": bool,
"outputPath": string,
"pageCount": int,
"fileSize": long
}
```
**Usage:** signFLOW (Envelope Generator), ErgebnisberichtCreator, ResultHandler (windream)
---
### Endpoint: PDF Stamp
**Route:** `POST /api/pdf/operations/stamp`
**Function:** Adds stamps to PDF pages (APPROVED, CONFIDENTIAL, etc.)
**Input:**
```json
{
"file": "PDF (multipart/form-data)",
"stamp": {
"text": string,
"position": string,
"pages": string,
"color": string,
"opacity": float
}
}
```
**Output:**
```json
{
"success": bool,
"outputPath": string
}
```
**Usage:** ErgebnisberichtCreator
---
### Endpoint: PDF Annotate
**Route:** `POST /api/pdf/operations/annotate`
**Function:** Adds comments, highlights, and markings to the PDF
**Input:**
```json
{
"file": "PDF (multipart/form-data)",
"annotations": [
{
"type": string,
"page": int,
"position": object,
"text": string
}
]
}
```
**Output:**
```json
{
"success": bool,
"outputPath": string
}
```
**Usage:** signFLOW (Envelope Generator)
---
## PdfRenderController
### Endpoint: PDF Preview
**Route:** `POST /api/pdf/render/preview`
**Function:** Renders PDF pages as PNG/JPEG for preview
**Input:**
```json
{
"file": "PDF (multipart/form-data)",
"page": int,
"format": string,
"dpi": int
}
```
**Output:**
```json
{
"images": [
{
"page": int,
"base64": string,
"width": int,
"height": int
}
]
}
```
**Usage:** taskFLOW, fileFLOW, easyFLOW, orgFLOW - PDF preview
---
## PdfConversionController
### Endpoint: Convert PDF to PDF/A
**Route:** `POST /api/pdf/conversion/to-pdfa`
**Function:** Converts a standard PDF to PDF/A
**Input:**
```json
{
"file": "PDF (multipart/form-data)",
"pdfaLevel": string
}
```
**Output:**
```json
{
"success": bool,
"outputPath": string,
"pdfaVersion": string
}
```
**Usage:** taskFLOW (optional conversion)
---
### Endpoint: Convert PDF/A to PDF
**Route:** `POST /api/pdf/conversion/from-pdfa`
**Function:** Converts PDF/A to a standard PDF
**Input:**
```json
{
"file": "PDF (multipart/form-data)"
}
```
**Output:**
```json
{
"success": bool,
"outputPath": string
}
```
**Usage:** taskFLOW (optional conversion)
---
## Technical Specifications
### Framework Support
- ✓ .NET Core (3.1+, 6.0+, 8.0+)
- ✓ .NET Framework (4.7.2+, 4.8+)
### Client Usage
The service can be used on the client side **without manual HTTP response handling**:
- Provide REST client wrapper
- SDK for C# clients
- Automatic serialization/deserialization
- Abstracted error handling
**Example Client SDK:**
```csharp
var client = new DocumentOperatorClient("https://api.example.com");
var result = await client.Pdf.Validation.ValidateAsync(pdfFile);
if (result.IsValid) { ... }
```
### Response Format
- Default: JSON
- Errors: HTTP Status Codes (400, 404, 500) + JSON error object
- Success: HTTP 200 + JSON response
### Authentication
- API Key (Header: `X-API-Key`)
- Optional: OAuth2/JWT for advanced scenarios
### Swagger/OpenAPI
- Complete API documentation
- Interactive test UI
- Code generation for clients
---
## Prioritization
### Phase 1 (Priority)
1. PdfValidationController - both endpoints
2. PdfAttachmentController - both endpoints
3. PdfOperationsController - Merge endpoint
### Phase 2
4. PdfOperationsController - Stamp & Annotate
5. PdfRenderController - Preview
### Phase 3
6. PdfConversionController - both endpoints
---
**Last Updated:** July 3, 2026
**Author:** Hakan Tek
**Status:** Draft - Awaiting Feedback

View File

@@ -1,5 +1,8 @@
namespace DocumentOperator.API.Configuration
{
/// <summary>
/// Placeholder class for Serilog configuration extensions.
/// </summary>
public class SerilogConfiguration
{
}

View File

@@ -3,8 +3,16 @@ using System.Reflection;
namespace DocumentOperator.API.Configuration
{
/// <summary>
/// Provides extension methods for configuring Swagger/OpenAPI documentation.
/// </summary>
public static class SwaggerConfiguration
{
/// <summary>
/// Adds Swagger documentation generation to the service collection.
/// </summary>
/// <param name="services">The service collection to add Swagger to.</param>
/// <returns>The modified service collection.</returns>
public static IServiceCollection AddSwaggerDocumentation(this IServiceCollection services)
{
services.AddSwaggerGen(options =>

View File

@@ -16,12 +16,21 @@ public class ExceptionHandlingMiddleware
private readonly RequestDelegate _next;
private readonly ILogger<ExceptionHandlingMiddleware> _logger;
/// <summary>
/// Initializes a new instance of the <see cref="ExceptionHandlingMiddleware"/> class.
/// </summary>
/// <param name="next">The next middleware in the pipeline.</param>
/// <param name="logger">The logger instance for exception logging.</param>
public ExceptionHandlingMiddleware(RequestDelegate next, ILogger<ExceptionHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}
/// <summary>
/// Invokes the middleware to handle incoming HTTP requests and catch exceptions.
/// </summary>
/// <param name="context">The HTTP context for the current request.</param>
public async Task InvokeAsync(HttpContext context)
{
try

View File

@@ -1,5 +1,8 @@
namespace DocumentOperator.API.Middleware
{
/// <summary>
/// Placeholder middleware for HTTP request/response logging.
/// </summary>
public class RequestLoggingMiddleware
{
}

View File

@@ -1,5 +1,8 @@
namespace DocumentOperator.API.Middleware
{
/// <summary>
/// Placeholder middleware for multi-tenancy resolution via X-API-Key header.
/// </summary>
public class TenantResolutionMiddleware
{
}

View File

@@ -3,7 +3,6 @@ using DocumentOperator.Infrastructure.Configuration;
using DocumentOperator.Application;
using DocumentOperator.Infrastructure;
using DocumentOperator.API.Middleware;
using DocumentOperator.API.Endpoints.v1;
using DocumentOperator.API.Configuration;
var builder = WebApplication.CreateBuilder(args);
@@ -41,6 +40,7 @@ try
builder.Services.AddApplication(); // Application Layer (MediatR, FluentValidation, Behaviors)
builder.Services.AddInfrastructure(); // Infrastructure Layer (DevExpress, Services)
builder.Services.AddControllers(); // Controllers (Controller-based API)
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerDocumentation();
@@ -67,9 +67,9 @@ try
app.UseHttpsRedirection();
// ========================================
// 6. Endpoints (Minimal API)
// 6. Endpoints (Controller-based API)
// ========================================
app.MapDocumentEndpoints(); // POST /api/v1/documents/validate
app.MapControllers(); // Maps all [ApiController] controllers
Log.Information("DocumentOperator API started successfully");
@@ -86,4 +86,8 @@ finally
}
// Make Program class accessible for Integration Tests
/// <summary>
/// Entry point class for the DocumentOperator API.
/// Made partial and public for integration test access.
/// </summary>
public partial class Program { }

View File

@@ -1,9 +1,11 @@
using Codecrete.SwissQRBill.Generator;
using DevExpress.Drawing;
using DevExpress.Pdf;
using DocumentOperator.Application.Common.Interfaces;
using DocumentOperator.Domain.Exceptions;
using DocumentOperator.Domain.ValueObjects;
using System.Drawing;
using System.Runtime.Versioning;
using ZXing;
namespace DocumentOperator.Infrastructure.Services.QrCodeProcessing;
@@ -17,6 +19,7 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
private const int QrCodeSearchDpi = 300; // High DPI for better QR code recognition
/// <inheritdoc />
[SupportedOSPlatform("windows")]
public async Task<SwissQrCodeData> ExtractSwissQrCodeAsync(byte[] pdfBytes, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(pdfBytes);
@@ -64,30 +67,39 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
/// <summary>
/// Renders a PDF page to a high-resolution bitmap for QR code detection
/// </summary>
private static Bitmap RenderPageToImage(PdfDocumentProcessor processor, int pageIndex)
private static DXBitmap RenderPageToImage(PdfDocumentProcessor processor, int pageIndex)
{
// Render page at high DPI for better QR code recognition
var pageImage = processor.CreateBitmap(pageIndex + 1, QrCodeSearchDpi);
var pageImage = processor.CreateDXBitmap(pageIndex + 1, QrCodeSearchDpi);
return pageImage;
}
/// <summary>
/// Decodes QR code from an image using ZXing library
/// Decodes QR code from a DXBitmap image using ZXing library
/// </summary>
private static string? DecodeQrCodeFromImage(Bitmap image)
[SupportedOSPlatform("windows")]
private static string? DecodeQrCodeFromImage(DXBitmap dxImage)
{
// Convert DXBitmap to System.Drawing.Bitmap via MemoryStream
using var ms = new MemoryStream();
dxImage.Save(ms, DXImageFormat.Png);
ms.Position = 0;
using var gdiImage = Image.FromStream(ms);
using var gdiBitmap = new Bitmap(gdiImage);
var reader = new ZXing.Windows.Compatibility.BarcodeReader
{
AutoRotate = true,
TryInverted = true,
Options = new ZXing.Common.DecodingOptions
{
PossibleFormats = new[] { BarcodeFormat.QR_CODE },
TryHarder = true
PossibleFormats = [BarcodeFormat.QR_CODE],
TryHarder = true,
TryInverted = true
}
};
var result = reader.Decode(image);
var result = reader.Decode(gdiBitmap);
return result?.Text;
}
@@ -155,7 +167,13 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
}
/// <summary>
/// Maps Codecrete Address to our AddressData value object
/// Maps Codecrete Address to our AddressData value object.
///
/// NOTE: AddressLine1 and AddressLine2 (Combined Address / K-Type) are deprecated
/// as of Swiss Payment Standards 2025 (effective 21 Nov 2025).
/// The Swiss QR Bill now mandates Structured Address (S-Type) format.
/// These fields are retained for backward compatibility with legacy QR codes
/// generated before the deprecation date.
/// </summary>
private static AddressData MapAddress(Codecrete.SwissQRBill.Generator.Address address)
{
@@ -165,8 +183,10 @@ public sealed class DevExpressSwissQrCodeProcessor : ISwissQrCodeProcessor
Name = address.Name ?? string.Empty,
Street = address.Street,
BuildingNumber = address.HouseNo,
#pragma warning disable CS0618 // AddressLine1/AddressLine2 obsolete but required for backward compatibility
AddressLine1 = address.AddressLine1,
AddressLine2 = address.AddressLine2,
#pragma warning restore CS0618
PostalCode = address.PostalCode ?? string.Empty,
City = address.Town ?? string.Empty,
Country = address.CountryCode ?? string.Empty

View File

@@ -13,6 +13,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumentOperator.Domain", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DocumentOperator.Tests", "DocumentOperator.Tests\DocumentOperator.Tests.csproj", "{32D2E997-3DA7-4061-8A50-DBB34BBC3E5A}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3F9E8D8E-1234-4567-89AB-CDEF01234567}"
ProjectSection(SolutionItems) = preProject
CONTROLLER_ENDPOINTS.md = CONTROLLER_ENDPOINTS.md
REQUIRED_FEATURES.md = REQUIRED_FEATURES.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU

557
REQUIRED_FEATURES.md Normal file
View File

@@ -0,0 +1,557 @@
# DocumentOperator - Required Functions and Features
**Project:** DocumentService (DOC)
**Ticket:** DOC-1 - GDPicture and Nutrient Replacing
**Owner:** Hakan Tek
**Last Updated:** 03.07.2026
---
## Overview
This document describes in detail all PDF processing functions that the DocumentOperator service must implement. These functions will be implemented using the DevExpress Office File API as a replacement for the GDPicture and Nutrient libraries.
---
## 1. Input Processing
### 1.1 PDF/A Validation
**Purpose:** Check whether a PDF file conforms to the PDF/A standard.
**What is PDF/A?**
- ISO standard PDF format for long-term archiving
- Versions: PDF/A-1, PDF/A-2, PDF/A-3
- Has restrictions to guarantee future accessibility
**Criteria to Check:**
- ✓ Are all fonts embedded? (required in PDF/A)
- ✓ Is encryption present? (prohibited in PDF/A)
- ✓ Are there external content links? (prohibited in PDF/A)
- ✓ Does it contain JavaScript? (prohibited in PDF/A)
- ✓ Is metadata correctly defined?
- ✓ Are color profiles defined?
- ✓ Is transparency usage compliant with the standard?
**Suggested API Endpoint:**
```
POST /api/pdf/validate-pdfa
Body: { "filePath": "string" } or multipart file upload
Response: {
"isValid": true/false,
"pdfaVersion": "PDF/A-2b",
"errors": [],
"warnings": []
}
```
**Example Usage Scenario:**
```
Input: invoice_2024.pdf
Output: {
"isValid": true,
"pdfaVersion": "PDF/A-3b",
"pageCount": 5,
"errors": [],
"warnings": ["Document contains optional content"]
}
```
---
### 1.2 Attachment Check
**Purpose:** Detect whether embedded files (attachments) exist inside a PDF file.
**What is an Attachment?**
- External files embedded inside a PDF
- Examples: XML, Excel, images, other PDFs
- Special use: XML data in ZUGFeRD/XRechnung e-invoices
**PDF/A Versions and Attachments:**
- PDF/A-1: NO attachment support
- PDF/A-2: NO attachment support
- PDF/A-3: Attachment support AVAILABLE (most common use)
**Suggested API Endpoint:**
```
POST /api/pdf/has-attachments
Response: {
"hasAttachments": true/false,
"attachmentCount": 2,
"attachments": [
{
"fileName": "factur-x.xml",
"mimeType": "application/xml",
"size": 12345,
"description": "ZUGFeRD Invoice Data"
}
]
}
```
---
### 1.3 Extract Attachments
**Purpose:** Extract all embedded files from a PDF and save them to the specified location.
**Usage Scenarios:**
- Extracting XML from ZUGFeRD e-invoices
- Retrieving attached documents from PDF/A-3 files
- Extracting embedded data for automated processing
**Suggested API Endpoint:**
```
POST /api/pdf/extract-attachments
Body: {
"filePath": "string",
"outputPath": "string",
"fileNamePattern": "{originalName}" // or "{index}_{originalName}"
}
Response: {
"success": true,
"extractedFiles": [
{
"fileName": "factur-x.xml",
"savedPath": "C:\\Temp\\Attachments\\factur-x.xml",
"size": 12345
}
]
}
```
**DevExpress Implementation Example:**
```csharp
using DevExpress.Pdf;
using (PdfDocumentProcessor processor = new PdfDocumentProcessor())
{
processor.LoadDocument("invoice.pdf");
foreach (PdfEmbeddedFile embeddedFile in processor.Document.EmbeddedFiles)
{
byte[] fileData = embeddedFile.GetData();
string outputPath = Path.Combine(targetFolder, embeddedFile.FileName);
File.WriteAllBytes(outputPath, fileData);
}
}
```
---
### 1.4 PDF File Validity Check
**Purpose:** Check whether a file is a genuine PDF and verify its structural integrity.
**Items to Check:**
- ✓ Is the file actually a PDF? (Magic bytes: %PDF-)
- ✓ Is the PDF header valid?
- ✓ Is the PDF structure not broken/corrupt?
- ✓ Can the file be opened?
- ✓ What is the PDF version? (1.4, 1.7, 2.0, etc.)
- ✓ Page count
- ✓ Can basic metadata be read?
**Suggested API Endpoint:**
```
POST /api/pdf/validate
Response: {
"isValid": true,
"pdfVersion": "1.7",
"pageCount": 5,
"fileSize": 524288,
"encrypted": false,
"errors": [],
"metadata": {
"title": "Invoice 2024",
"author": "Company XYZ",
"creationDate": "2024-01-15T10:30:00"
}
}
```
**Error Scenarios:**
```
Scenario 1 - Corrupt file:
{
"isValid": false,
"errors": ["PDF header is missing or corrupted"]
}
Scenario 2 - Wrong format:
{
"isValid": false,
"errors": ["File is not a PDF (detected: JPEG image)"]
}
```
---
## 2. PDF Processing Operations
### 2.1 PDF Merge (Concatenate/Merge)
**Purpose:** Merge multiple PDF files into a single PDF.
**Usage Areas:**
- **signFLOW (Envelope Generator):** Merging multiple documents into a single envelope
- **ErgebnisberichtCreator:** Merging report sections
- **ResultHandler (windream):** Document merging
**Suggested API Endpoint:**
```
POST /api/pdf/merge
Body: {
"sourceFiles": ["file1.pdf", "file2.pdf", "file3.pdf"],
"outputPath": "merged.pdf",
"options": {
"addBookmarks": true,
"preserveMetadata": true,
"compressionLevel": "medium"
}
}
Response: {
"success": true,
"outputPath": "merged.pdf",
"pageCount": 15,
"fileSize": 1048576
}
```
**Features:**
- Preserve page order
- Add bookmarks (for each source file)
- Merge metadata
- Preserve PDF/A compliance
---
### 2.2 Stamping
**Purpose:** Add a stamp to PDF pages - e.g. "APPROVED", "CONFIDENTIAL", "DRAFT"
**Usage Area:**
- **ErgebnisberichtCreator:** Approval/status stamps on reports
**Suggested API Endpoint:**
```
POST /api/pdf/stamp
Body: {
"filePath": "document.pdf",
"stamp": {
"text": "APPROVED",
"position": "TopRight", // TopLeft, TopRight, BottomLeft, BottomRight, Center
"pages": "all", // or "1,3,5" or "1-5"
"color": "#FF0000",
"opacity": 0.5,
"rotation": 45,
"fontSize": 48
}
}
```
**Stamp Types:**
- Text stamp
- Image stamp (logo, signature)
- QR code stamp
- Date/time stamp
---
### 2.3 Annotation
**Purpose:** Add comments, highlights, notes, and drawings to a PDF.
**Usage Area:**
- **signFLOW:** Signature fields, comments, highlights
**Annotation Types:**
- Text annotations (comments)
- Highlight
- Underline
- Strikeout
- Shapes (rectangle, circle, arrow)
- Stamps (predefined stamps)
**Suggested API Endpoint:**
```
POST /api/pdf/annotate
Body: {
"filePath": "document.pdf",
"annotations": [
{
"type": "highlight",
"page": 1,
"rect": {"x": 100, "y": 200, "width": 200, "height": 20},
"color": "#FFFF00"
},
{
"type": "text",
"page": 1,
"position": {"x": 100, "y": 250},
"text": "This section is important!",
"author": "Hakan Tek"
}
]
}
```
---
### 2.4 PDF/A Conversion
**Purpose:** PDF ↔ PDF/A format conversion.
**Usage Area:**
- **taskFLOW:** Converting PDF/A to standard PDF (optional)
**Two-Way Operation:**
#### A) PDF → PDF/A (For archiving)
```
POST /api/pdf/convert-to-pdfa
Body: {
"filePath": "document.pdf",
"pdfaLevel": "PDF/A-2b", // or PDF/A-1b, PDF/A-3b
"embedFonts": true,
"colorProfile": "sRGB"
}
```
#### B) PDF/A → PDF (Remove restrictions)
```
POST /api/pdf/convert-from-pdfa
Body: {
"filePath": "document-pdfa.pdf",
"removeRestrictions": true
}
```
**During Conversion:**
- Embed all fonts
- Remove JavaScript
- Resolve external references
- Add color profiles
- Metadata standardization
---
## 3. PDF Rendering (Preview/Rendering)
### 3.1 PDF Preview
**Purpose:** Render PDF pages and return them as images (PNG/JPEG).
**Usage Areas:**
- **taskFLOW:** PDF preview
- **fileFLOW:** PDF preview
- **easyFLOW:** PDF preview
- **orgFLOW:** PDF preview
**Suggested API Endpoint:**
```
POST /api/pdf/render
Body: {
"filePath": "document.pdf",
"page": 1, // or "all"
"format": "png", // or "jpeg"
"dpi": 150,
"width": 800, // optional, aspect ratio preserved
"quality": 85 // for JPEG
}
Response: {
"images": [
{
"page": 1,
"base64": "iVBORw0KGgoAAAANS...",
"width": 800,
"height": 1132
}
]
}
```
**Features:**
- Page selection (single page or all)
- Configurable DPI
- Format selection (PNG, JPEG)
- Thumbnail generation
---
## 4. Advanced Functions
### 4.1 Text Extraction
**Purpose:** Extract plain text from a PDF.
```
POST /api/pdf/extract-text
Response: {
"text": "Extracted text content...",
"pageTexts": [
{ "page": 1, "text": "Page 1 content..." },
{ "page": 2, "text": "Page 2 content..." }
]
}
```
---
### 4.2 Metadata Read/Write
**Purpose:** Read and update PDF metadata.
```
GET /api/pdf/metadata?filePath=document.pdf
Response: {
"title": "Invoice 2024",
"author": "Company XYZ",
"subject": "Monthly Invoice",
"keywords": ["invoice", "payment"],
"creator": "Microsoft Word",
"producer": "Adobe PDF Library",
"creationDate": "2024-01-15T10:30:00",
"modificationDate": "2024-01-15T14:45:00"
}
POST /api/pdf/metadata
Body: {
"filePath": "document.pdf",
"metadata": {
"title": "Updated Title",
"author": "New Author"
}
}
```
---
### 4.3 Form Field Operations
**Purpose:** Read and fill fields in PDF forms.
```
GET /api/pdf/form-fields
Response: {
"fields": [
{ "name": "customerName", "type": "text", "value": "" },
{ "name": "invoiceDate", "type": "text", "value": "" },
{ "name": "approved", "type": "checkbox", "value": false }
]
}
POST /api/pdf/fill-form
Body: {
"filePath": "form.pdf",
"fields": {
"customerName": "ACME Corp",
"invoiceDate": "2024-07-03",
"approved": true
},
"flatten": true // Make fields non-editable
}
```
---
## 5. Priority Order
### Phase 1 - Core Functions (PRIORITY)
1. ✓ PDF Validation (1.4)
2. ✓ PDF/A Validation (1.1)
3. ✓ Attachment Check (1.2)
4. ✓ Extract Attachments (1.3)
5. ✓ PDF Merge (2.1)
### Phase 2 - Advanced Functions
6. ✓ Stamping (2.2)
7. ✓ Annotation (2.3)
8. ✓ PDF Preview/Rendering (3.1)
### Phase 3 - Conversion and Extras
9. ✓ PDF/A Conversion (2.4)
10. ✓ Text Extraction (4.1)
11. ✓ Metadata Operations (4.2)
12. ✓ Form Field Operations (4.3)
---
## 6. Technical Requirements
### 6.1 Library to Use
- **DevExpress Office File API (PDF Document API)**
- NuGet: `DevExpress.Pdf`
- License: Existing DevExpress license
### 6.2 REST API Requirements
- HTTP REST endpoints
- JSON request/response
- Swagger/OpenAPI documentation
- File upload support (multipart/form-data)
### 6.3 Performance Goals
- Asynchronous processing (async/await)
- Large file support (streaming)
- Memory optimization
- Parallel processing support
### 6.4 Error Handling
- Detailed error messages
- HTTP status codes (400, 404, 500, etc.)
- Validation errors
- Logging (Serilog recommended)
---
## 7. Test Strategy
### Unit Tests
- Separate test for each function
- Various PDF versions
- Edge cases (empty file, corrupt PDF, etc.)
### Integration Tests
- API endpoint tests
- File upload/download tests
- End-to-end scenarios
### Test Files
- Valid PDF
- Valid PDF/A (1b, 2b, 3b)
- Corrupt PDF
- PDF with attachments
- PDF with forms
- Encrypted PDF
- Large files (>100MB)
---
## 8. Documentation Requirements
### Swagger/OpenAPI
- Detailed description for all endpoints
- Request/Response examples
- Error codes description
- Authentication (if applicable)
### Code Documentation
- XML comments (for C#)
- Interface documentation
- Usage examples
---
## References
- **DevExpress PDF API Documentation:** https://docs.devexpress.com/OfficeFileAPI/
- **PDF/A Standard:** ISO 19005
- **ZUGFeRD Standard:** https://www.ferd-net.de/
- **Ticket:** DOC-1 (M:\Austausch\DocumentOperator)
---
**Last Updated:** 03.07.2026
**Prepared by:** Hakan Tek
**Status:** Initial Draft