Внутрішня будова 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()) # 2Document.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/шрифтові ресурси |
EncryptionUtils | AES-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 афінних перетворень, що використовуються по всьому движку |