Валідація PDF/A
PDF/A (ISO 19005) — це міжнародний стандарт для довгострокового архівування електронних документів. PDF Oxide валідує всі основні рівні PDF/A та може конвертувати невідповідні документи у напрямку відповідності.
Підтримувані рівні
| Рівень | Стандарт | Структура | Unicode | Прозорість | Вбудовані файли |
|---|---|---|---|---|---|
| 1a | ISO 19005-1 | Required | Required | No | No |
| 1b | ISO 19005-1 | No | No | No | No |
| 2a | ISO 19005-2 | Required | Required | Yes | No |
| 2b | ISO 19005-2 | No | No | Yes | No |
| 2u | ISO 19005-2 | No | Required | Yes | No |
| 3a | ISO 19005-3 | Required | Required | Yes | Yes |
| 3b | ISO 19005-3 | No | No | Yes | Yes |
| 3u | ISO 19005-3 | No | Required | Yes | Yes |
Рівень “a” (accessible, доступний) вимагає тегованого дерева структури та відображення символів Unicode. Рівень “b” (basic, базовий) вимагає лише візуальної відтворюваності. Рівень “u” (Unicode) вимагає відображення тексту Unicode без повного дерева структури.
Швидка валідація
Використовуйте зручну функцію для перевірки за один виклик:
from pdf_oxide import PdfDocument
doc = PdfDocument("document.pdf")
result = doc.validate_pdf_a("2b")
print(f"Valid: {result.valid}")
print(f"Level: {result.level}")
for error in result.errors:
print(f" Error: {error}")
const doc = new WasmPdfDocument(bytes);
const result = doc.validatePdfA("2b");
console.log(`Valid: ${result.valid}`);
console.log(`Errors: ${result.errors.length}`);
doc.free();
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, PdfALevel};
let mut doc = PdfDocument::open("archive.pdf")?;
let result = validate_pdf_a(&mut doc, PdfALevel::A1b)?;
if result.has_errors() {
println!("Not PDF/A-1b compliant:");
for error in &result.errors {
println!(" [{}] {} (clause {})",
error.code, error.message,
error.clause.as_deref().unwrap_or("n/a"));
}
} else {
println!("Document is PDF/A-1b compliant");
}
API валідатора
PdfAValidator надає шаблон builder для детального контролю:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};
let mut doc = PdfDocument::open("report.pdf")?;
let result = PdfAValidator::new()
.stop_on_first_error(false)
.include_warnings(true)
.validate(&mut doc, PdfALevel::A2b)?;
println!("Errors: {}", result.errors.len());
println!("Warnings: {}", result.warnings.len());
Цільові перевірки
Запуск окремих категорій валідації замість повного набору:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAValidator, PdfALevel};
let mut doc = PdfDocument::open("report.pdf")?;
let validator = PdfAValidator::new();
// Check only metadata
let result = validator.check_metadata(&mut doc, PdfALevel::A1b)?;
// Check only fonts
let result = validator.check_fonts(&mut doc, PdfALevel::A1b)?;
// Check only color spaces
let result = validator.check_colors(&mut doc, PdfALevel::A1b)?;
// Check only transparency
let result = validator.check_transparency(&mut doc, PdfALevel::A2b)?;
// Check only structure tags
let result = validator.check_structure(&mut doc, PdfALevel::A1a)?;
Окремі валідатори
Кожна категорія валідації також доступна як окрема функція для максимальної гнучкості:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::validators::*;
use pdf_oxide::compliance::{PdfALevel, ValidationResult};
let mut doc = PdfDocument::open("document.pdf")?;
let mut result = ValidationResult::new(PdfALevel::A1b);
// Run each validator independently
validate_xmp_metadata(&mut doc, PdfALevel::A1b, &mut result)?;
validate_fonts(&mut doc, PdfALevel::A1b, &mut result)?;
validate_colors(&mut doc, PdfALevel::A1b, &mut result)?;
validate_encryption(&mut doc, PdfALevel::A1b, &mut result)?;
validate_transparency(&mut doc, PdfALevel::A1b, &mut result)?;
validate_structure(&mut doc, PdfALevel::A1b, &mut result)?;
validate_javascript(&mut doc, PdfALevel::A1b, &mut result)?;
validate_embedded_files(&mut doc, PdfALevel::A1b, &mut result)?;
validate_annotations(&mut doc, PdfALevel::A1b, &mut result)?;
println!("Total errors: {}", result.errors.len());
Підсумок валідатора
| Функція | Що перевіряє |
|---|---|
validate_xmp_metadata() |
XMP stream exists, pdfaid:part and pdfaid:conformance entries present, metadata consistency |
validate_fonts() |
All fonts embedded, glyph widths present, Unicode mapping available (for level “a” and “u”) |
validate_colors() |
No device-dependent color operators (rg, RG, k, K, g, G) without output intent |
validate_encryption() |
No encryption permitted in PDF/A documents |
validate_transparency() |
No transparency in PDF/A-1; allowed in PDF/A-2 and later |
validate_structure() |
Теговане дерево структури present with valid role mapping (required for level “a”) |
validate_javascript() |
No JavaScript actions or triggers present |
validate_embedded_files() |
Not allowed in PDF/A-1 or PDF/A-2; PDF/A-3 requires AFRelationship key on each file spec |
validate_annotations() |
Тип анотаціїs restricted per the relevant ISO 19005 part |
ValidationResult
Структура ValidationResult містить повний результат перевірки валідації:
pub struct ValidationResult {
pub level: PdfALevel,
pub errors: Vec<ComplianceError>,
pub warnings: Vec<ComplianceWarning>,
pub stats: ValidationStats,
}
| Поле | Тип | Опис |
|---|---|---|
level |
PdfALevel |
The target compliance level |
errors |
Vec<ComplianceError> |
Blocking violations that prevent compliance |
warnings |
Vec<ComplianceWarning> |
Non-blocking issues that may affect quality |
stats |
ValidationStats |
Counts of pages, fonts, and objects checked |
ComplianceError
pub struct ComplianceError {
pub code: ErrorCode,
pub message: String,
pub location: Option<String>,
pub clause: Option<String>,
}
Поле code використовує enum ErrorCode with categories like MissingXmpMetadata, FontNotEmbedded, DeviceDependentColor, EncryptionPresent, TransparencyNotAllowed, MissingStructureTree, JavaScriptPresent, and InvalidEmbeddedFile.
ComplianceWarning
pub struct ComplianceWarning {
pub code: WarningCode,
pub message: String,
pub location: Option<String>,
}
Конвертація PDF/A
Конвертувати невідповідний документ у напрямку відповідності PDF/A:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{convert_to_pdf_a, PdfALevel};
let mut doc = PdfDocument::open("input.pdf")?;
let result = convert_to_pdf_a(&mut doc, PdfALevel::A1b)?;
println!("Conversion actions taken:");
for action in &result.actions {
println!(" - {}: {}", action.action_type, action.description);
}
if result.remaining_errors.is_empty() {
println!("Document is now PDF/A-1b compliant");
} else {
println!("{} issues could not be resolved automatically",
result.remaining_errors.len());
}
Конвертація Config
Fine-tune the conversion process:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{PdfAConverter, PdfALevel, ConversionConfig};
let mut doc = PdfDocument::open("input.pdf")?;
let config = ConversionConfig::new()
.embed_fonts(true)
.remove_javascript(true)
.flatten_transparency(true)
.add_structure(true);
let result = PdfAConverter::new(PdfALevel::A2b)
.with_config(config)
.convert(&mut doc)?;
Конвертер виконує ці дії автоматично:
- XMP metadata injection – adds
pdfaid:partandpdfaid:conformanceentries - Font embedding – embeds any referenced but non-embedded fonts
- JavaScript removal – strips JavaScript actions and triggers
- Transparency flattening – renders transparent elements to opaque (PDF/A-1 only)
- ICC profile conversion – converts device-dependent colors to ICC-based color spaces
- Structure tagging – adds basic structure tags (for level “a” targets)
Робочий процес: Валідація, Виправлення, Повторна валідація
A typical archival workflow validates, attempts automatic conversion, then re-validates:
use pdf_oxide::PdfDocument;
use pdf_oxide::compliance::{validate_pdf_a, convert_to_pdf_a, PdfALevel};
let level = PdfALevel::A2b;
let mut doc = PdfDocument::open("input.pdf")?;
// Step 1: Initial validation
let result = validate_pdf_a(&mut doc, level)?;
if !result.has_errors() {
println!("Already compliant");
return Ok(());
}
println!("{} errors found, attempting conversion...", result.errors.len());
// Step 2: Automatic conversion
let conversion = convert_to_pdf_a(&mut doc, level)?;
println!("{} actions taken", conversion.actions.len());
// Step 3: Re-validate
let result = validate_pdf_a(&mut doc, level)?;
if result.has_errors() {
println!("{} errors remain after conversion:", result.errors.len());
for e in &result.errors {
println!(" {} -- {}", e.code, e.message);
}
} else {
println!("Document is now PDF/A-2b compliant");
}
Методи PdfALevel
Enum PdfALevel містить допоміжні методи для запиту можливостей рівня:
| Метод | Повертає | Опис |
|---|---|---|
part() |
PdfAPart |
ISO 19005 part (Part1, Part2, Part3) |
conformance() |
char |
Conformance letter (‘a’, ‘b’, or ‘u’) |
requires_structure() |
bool |
Whether tagged structure tree is mandatory |
requires_unicode() |
bool |
Whether Unicode mapping is mandatory |
allows_transparency() |
bool |
Whether transparency is permitted |
allows_jpeg2000() |
bool |
Whether JPEG 2000 images are permitted |
allows_embedded_files() |
bool |
Whether file attachments are permitted |
xmp_part() |
&str |
XMP pdfaid:part value |
xmp_conformance() |
&str |
XMP pdfaid:conformance value |
from_xmp(part, conformance) |
Option<Self> |
Parse level from XMP metadata values |
Наступні кроки
- PDF/UA Accessibility – accessibility validation
- PDF/X Print Production – print production validation
- API Reference – complete Rust API