Внутрішня будова PDF Processing Engine

Внутрішня будова PDF Processing Engine

Внутрішня будова PDF-обробного движка

Document, Page та Annotation класи, які ви використовуєте для щоденної обробки PDF, є фасадом над нижчорівневим пакетом aspose_pdf.engine. Движок реалізує справжню механіку PDF: модель об’єктів COS (Carousel Object Structure), з якої будується кожен PDF-файл, парсер і записувач, що перетворюють між об’єктами COS і PDF-байтами, синтез зовнішнього вигляду анотацій, растеризацію сторінок, внутрішню роботу шрифтів і кодеків зображень, а також криптографічні примітиви, що стоять за шифруванням документів і цифровими підписами. Більшість застосунків ніколи не потребують імпортувати безпосередньо з aspose_pdf.engine — проте це правильне місце для пошуку, коли потрібні власні інструменти, судова PDF-аналіз або функціональність, яку високорівневий API не розкриває.


Створення зовнішнього вигляду для однієї анотації

Інтерактивні анотації, такі як квадрати, кола та штампи, не містять автоматично звичайного потоку зовнішнього вигляду (/AP /N). Виклик Annotation.generate_appearance активує внутрішні механізми синтезу зовнішнього вигляду движка, щоб створити його за вимогою на основі властивостей анотації.

from aspose_pdf import Document

doc = Document()
doc.pages.add()
ann = doc.pages[0].annotations.add(
    "Square", (100, 100, 200, 200), "", properties={"C": [1, 0, 0], "IC": [0, 1, 0]}
)

print(ann.has_appearance)  # False -- no appearance stream yet
ann.generate_appearance()
print(ann.has_appearance)  # True -- the engine synthesised one
print(b"1 0 0 RG" in ann.appearance_normal)  # True -- red stroke operator
print(b"0 1 0 rg" in ann.appearance_normal)  # True -- green fill operator

Пакетне створення зовнішнього вигляду на всіх сторінках та в документах

AnnotationCollection.generate_appearances синтезує зовнішній вигляд для кожної придатної анотації на сторінці одним викликом, пропускаючи підтипи, які движок не вміє відображати (наприклад, Text):

from aspose_pdf import Document

doc = Document()
doc.pages.add()
page = doc.pages[0]
page.annotations.add("Square", (0, 0, 50, 50), "")
page.annotations.add("Circle", (60, 0, 110, 50), "")
page.annotations.add("Text", (0, 60, 20, 80), "")  # unsupported subtype -> skipped

print(page.annotations.generate_appearances())  # 2

Document.generate_appearances робить те ж саме на всіх сторінках документа і є ідемпотентним — другий виклик не виконує жодних дій, якщо зовнішні вигляди вже існують:

from aspose_pdf import Document

doc = Document()
doc.pages.add()
doc.pages.add()
doc.pages[0].annotations.add("Square", (0, 0, 50, 50), "")
doc.pages[1].annotations.add(
    "Line", (0, 0, 50, 50), "", properties={"L": [0, 0, 50, 50]}
)

print(doc.generate_appearances())  # 2 -- one per page
print(doc.generate_appearances())  # 0 -- already generated, no-op

Згладжування анотацій у статичний вміст сторінки

Document.flatten() малює зовнішній вигляд кожної анотації безпосередньо у потік вмісту сторінки (як виклик Do XObject) і потім видаляє сам об’єкт анотації, тож сторінка відображається ідентично у переглядачах, які повністю ігнорують анотації:

from aspose_pdf import Document

doc = Document()
doc.pages.add()
doc.pages[0].annotations.add(
    "Square", (100, 100, 200, 200), "", properties={"C": [0, 0, 0]}
)

doc.flatten()

Після цього виклику потік вмісту сторінки стає довшим, ніж раніше (тепер він містить вбудований квадрат), і doc.pages[0].annotations більше не містить згладжену анотацію.


Виведення ключів шифрування на основі пароля (Revision 4 / AES-128)

EncryptionUtils реалізує безпосередньо виведення ключа та примітиви AES-CBC стандартного обробника безпеки PDF, незалежно від Document API. Це корисно для спеціальних інструментів або судово-експертної перевірки зашифрованих PDF:

import os
from aspose_pdf.engine.encryption import EncryptionUtils

file_id = os.urandom(16)
user_pwd = "mypassword"

# Derive the owner (O) and user (U) key material for Revision 4 (128-bit AES)
o_value = EncryptionUtils.compute_owner_key_v4("owner", user_pwd, 16, 4)
u_value, enc_key = EncryptionUtils.compute_user_key_v4(
    user_pwd, o_value, -4, file_id, 16, 4
)

# Encrypt data with the derived file-encryption key
plaintext = b"Confidential PDF content"
ciphertext = EncryptionUtils.encrypt_aes_cbc(enc_key, plaintext)

# Re-derive the key from the password before trusting it to decrypt
verified_key = EncryptionUtils.verify_password_v4(
    user_pwd, u_value, o_value, -4, file_id, 16, 4
)
print(verified_key is not None)  # True -- password matches

decrypted = EncryptionUtils.decrypt_aes_cbc(verified_key, ciphertext)
print(decrypted == plaintext)  # True

Шифрування сирого вмісту за допомогою AES-CBC

Для низькорівневих потреб EncryptionUtils.encrypt_aes_cbc() і decrypt_aes_cbc() працюють безпосередньо з будь-яким 16-, 24- або 32-байтовим ключем, не проходячи взагалі через виведення ключа на основі пароля:

import os
from aspose_pdf.engine.encryption import EncryptionUtils

key = os.urandom(32)  # AES-256; 16 and 24-byte keys are also accepted
plaintext = b"Hello, PDF AES 256!"

ciphertext = EncryptionUtils.encrypt_aes_cbc(key, plaintext)
decrypted = EncryptionUtils.decrypt_aes_cbc(key, ciphertext)
print(decrypted == plaintext)  # True

Поради та найкращі практики

  • Віддавайте перевагу високорівневій фасаді Document, Page і Annotation для щоденної обробки документів. Пакет aspose_pdf.engine є внутрішньою реалізацією, на якій побудовані ці класи — використовуйте його лише коли потрібні спеціальні інструменти, судово-кримінальна інспекція або функціональність, яку фасад не розкриває.
  • Задайте аргумент revision відповідно до обробника безпеки, який ви цілите: compute_owner_key_v4/compute_user_key_v4 охоплює редакції 2–4 (40- і 128-бітові RC4/AES), тоді як compute_hash_v5 реалізує алгоритм редакції 5/6, який використовується AES-256. Змішування редакцій та довжин ключа без повідомлення призводить до неправильного ключа.
  • Document.generate_appearances і AnnotationCollection.generate_appearances є ідемпотентними — викликайте їх обережно перед рендерингом або сплющуванням документа, який ви не створювали.
  • Document.flatten() є руйнівним: він видаляє всі анотації, які він вписує у вміст сторінки. Завершіть будь-яке інше редагування анотацій спочатку, або працюйте з копією.
  • Не кожен підтип анотації має вбудований синтезатор вигляду — Text і Popup є поширеними прикладами. Перевірте has_appearance після виклику generate_appearance(), а не припускайте, що операція успішна.

Поширені проблеми

ПроблемаПричинаВиправлення
EncryptionUtils.encrypt_aes_cbc/decrypt_aes_cbc викликає помилку “AES key must be 16, 24, or 32 bytes”Надано ключ неправильної довжиниЗгенеруйте ключ за допомогою os.urandom(16), os.urandom(24) або os.urandom(32)
EncryptionUtils.verify_password_v4 повертає None замість підняттяНаданий пароль не відповідає отриманим документом значенням U/OЯвно перевірте None перед передачею результату до decrypt_aes_cbc
Annotation.generate_appearance повертає FalseПідтип анотації не має вбудованого синтезатора вигляду (наприклад Text або Popup)Надайте свої власні байти appearance_normal, або прийміть типове відображення переглядача
Другий виклик Document.generate_appearances повертає 0Виклик є ідемпотентним — анотації, які вже мають has_appearance == True, пропускаютьсяОчікувана поведінка, а не помилка

FAQ

Чи потрібно імпортувати з aspose_pdf.engine для щоденної обробки документів?

Ні. Класи Document, Page та Annotation охоплюють стандартні робочі процеси документів. Шар двигуна — це місце, де реалізується поведінка цих класів, і він найкорисніший для власних інструментів або прямого вивчення внутрішньої структури PDF.

Яка різниця між Annotation.generate_appearance та AnnotationCollection.generate_appearances?

Перший синтезує потік вигляду для однієї анотації і повертає bool. Другий робить те ж саме для кожної придатної анотації у колекції (анотації сторінки або, за допомогою Document.generate_appearances, для кожної сторінки документа) і повертає кількість створених виглядів.

Чому методи виведення ключа приймають аргумент revision?

Обробник безпеки стандарту PDF розвивався в різних редакціях ISO 32000 — Ревізія 2 використовує 40-бітний RC4, Ревізії 3/4 підтримують 128-бітний RC4 або AES, а Ревізії 5/6 (використовуються для AES-256) застосовують зовсім інший алгоритм хешування (compute_hash_v5). Аргумент revision вибирає, яке виведення виконують методи EncryptionUtils.

Чи можу я безпосередньо переглядати або створювати необроблені PDF-об’єкти?

Так. aspose_pdf.engine.cos розкриває модель об’єктів COS — PdfObject, PdfDictionary, PdfArray, PdfStream, PdfName та пов’язані типи — які PdfCosWriter та PdfCosParser серіалізують у байти PDF і розбирають з них.

Де відбувається рендеринг сторінки у зображення?

Document.render_page повертає RasterizedPage, об’єкт рівня рушія з методами to_png(), to_tiff() та save() для перетворення відрендереної сторінки у файл зображення.


API Reference Підсумок

Клас / МетодОпис
Annotation.generate_appearance(force) -> boolСинтезувати нормальний потік вигляду для однієї анотації за запитом
AnnotationCollection.generate_appearances(force) -> intПакетно генерувати вигляди для кожної придатної анотації на сторінці
Document.generate_appearances(force) -> intПакетно генерувати вигляди для кожної придатної анотації в документі
Document.flatten() -> DocumentВбудувати вигляди анотацій у вміст сторінки і видалити анотації
Document.render_page(page_index, dpi, scale, background, antialias) -> RasterizedPageРастеризувати сторінку через конвеєр рендерингу движка
RasterizedPageВідрендерена сторінка у упакованому форматі RGB, з to_png(), to_tiff() та save()
GeneratedAppearanceВнутрішній результат синтезу зовнішнього вигляду: байти вмісту плюс будь-які необхідні ExtGState/шрифтові ресурси
EncryptionUtilsAES-CBC/RC4 шифрування та виведення ключа стандартного обробника безпеки PDF (Редакції 2–6)
PdfObjectАбстрактний базовий клас для кожного об’єкта COS (Carousel Object Structure)
PdfDictionary / PdfArray / PdfStreamКонкретні типи контейнерів COS, які утворюють низькорівневе дерево документа
PdfName / PdfNumber / PdfString / PdfBoolean / PdfNullПримітивні типи значень COS
PdfIndirectReferenceНепряме посилання COS (n g R) на інший об’єкт
PdfCosWriterСеріалізує в пам’яті COS PdfDocument у PDF-байти
PdfCosParser / LazyPdfObjectStoreРозбирає PDF-байти у COS-об’єкти, матеріалізуючи їх за потребою
IncrementalUpdate / IncrementalWriterДодає інкрементальний розділ оновлення до існуючого PDF замість його перезапису
SimplePdfНативне-Python низькорівневе представлення документа, на якому побудовано високорівневий Document API
TextFragmentAbsorber / TextFragmentCollectionНизькорівневе видобування текстових фрагментів над екземпляром SimplePdf instance
ImagePlacementAbsorber / ImagePlacementЗнаходьте, зберігайте, замінюйте або приховуйте растрові зображення, розташовані на сторінці
SigningUtilsСтворюйте самопідписані сертифікати та підписи PKCS#7/CAdES для цифрового підпису
DssMaterial / ChainResult / RevocationResult / TimestampInfoПідтримка валідації підпису: матеріали DSS, результати ланцюжка сертифікатів, перевірки відкликання та верифікація часових міток RFC 3161
StandardFontsМетрики та кодування для 14 стандартних шрифтів PDF
CidTextCodecКодувати та декодувати show-strings для композитних (Type0) шрифтів
ShadingЗразок кольору RGB у аксіальних, радіальних та функціональних shading-ах
Color / MatrixНизькорівневі примітиви кольору та 2-D афінних перетворень, що використовуються по всьому движку

Дивіться також

 Українська