Internes du moteur de traitement PDF
Internaux du moteur de traitement PDF
Les classes Document, Page et Annotation que vous utilisez pour le traitement quotidien des PDF sont une façade sur un package aspose_pdf.engine de niveau inférieur. Le moteur implémente les mécanismes réels du PDF: le modèle d’objet COS (Carousel Object Structure) dont chaque fichier PDF est construit, l’analyseur et l’écrivain qui convertissent entre les objets COS et les octets PDF, la synthèse de l’apparence des annotations, la rasterisation des pages, les internes des codecs de polices et d’images, ainsi que les primitives cryptographiques derrière le chiffrement des documents et les signatures numériques. La plupart des applications n’ont jamais besoin d’importer directement depuis aspose_pdf.engine — mais c’est l’endroit approprié à consulter lorsque vous avez besoin d’outils personnalisés, d’une inspection médico-légale de PDF, ou d’un comportement que le API de haut niveau n’expose pas.
Génération d’une apparence pour une annotation unique
Les annotations interactives telles que les carrés, les cercles et les tampons ne contiennent pas automatiquement un flux d’apparence normal (/AP /N). Appeler Annotation.generate_appearance déclenche les internes de synthèse d’apparence du moteur pour en créer un à la demande à partir des propriétés de l’annotation.
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 operatorGénération par lots d’apparences à travers les pages et les documents
AnnotationCollection.generate_appearances synthétise les apparences pour chaque annotation admissible sur une page en un seul appel, en sautant les sous-types que le moteur ne sait pas rendre (comme 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 fait de même sur chaque page du document, et est idempotent — un second appel ne fait rien une fois les apparences déjà présentes:
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-opAplatissement des annotations dans le contenu de page statique
Document.flatten() dessine l’apparence de chaque annotation directement dans le flux de contenu de sa page (comme une invocation XObject Do) et supprime ensuite l’objet annotation lui-même, de sorte que la page s’affiche identiquement dans les visionneuses qui ignorent complètement les annotations :
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()Après cet appel, le flux de contenu de la page est plus long qu’auparavant (il contient désormais le carré intégré) et doc.pages[0].annotations ne contient plus l’annotation aplatie.
Dérivation des clés de chiffrement basées sur le mot de passe (Révision 4 / AES-128)
EncryptionUtils implémente directement la dérivation de clés du gestionnaire de sécurité standard PDF et les primitives AES-CBC, indépendamment du Document API. Cela est utile pour des outils personnalisés ou une inspection légale de PDFs chiffrés :
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) # TrueChiffrement du contenu brut avec AES-CBC
Pour des besoins de bas niveau, EncryptionUtils.encrypt_aes_cbc() et decrypt_aes_cbc() travaillent directement sur toute clé de 16, 24 ou 32 octets sans passer par la dérivation de clé basée sur le mot de passe du tout :
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) # TrueConseils et meilleures pratiques
- Privilégiez la façade de haut niveau
Document,PageetAnnotationpour le traitement quotidien des documents. Le packageaspose_pdf.engineest l’implémentation interne sur laquelle ces classes sont construites — ne l’utilisez que lorsque vous avez besoin d’outils personnalisés, d’une inspection médico-légale ou d’un comportement que la façade n’expose pas. - Faites correspondre l’argument
revisionau gestionnaire de sécurité que vous ciblez:compute_owner_key_v4/compute_user_key_v4couvrent les Révisions 2–4 (RC4/AES 40 bits et 128 bits), tandis quecompute_hash_v5implémente l’algorithme des Révisions 5/6 utilisé par AES-256. Mélanger les révisions et les longueurs de clé produit silencieusement la mauvaise clé. Document.generate_appearancesetAnnotationCollection.generate_appearancessont idempotents — appelez-les de manière défensive avant de rendre ou d’aplatir un document que vous n’avez pas créé vous-même.Document.flatten()est destructif: il supprime chaque annotation qu’il insère dans le contenu de la page. Terminez d’abord toute autre modification d’annotation, ou travaillez sur une copie.- Tous les sous-types d’annotation n’ont pas de synthétiseur d’apparence intégré —
TextetPopupen sont des exemples courants. Vérifiezhas_appearanceaprès avoir appelégenerate_appearance()au lieu de supposer qu’il a réussi.
Problèmes courants
| Problème | Cause | Correction |
|---|---|---|
EncryptionUtils.encrypt_aes_cbc/decrypt_aes_cbc génère une erreur “AES key must be 16, 24, or 32 bytes” | Une clé d’une longueur invalide a été fournie | Générez la clé avec os.urandom(16), os.urandom(24) ou os.urandom(32) |
EncryptionUtils.verify_password_v4 renvoie None au lieu de lever | Le mot de passe fourni ne correspond pas aux valeurs U/O dérivées du document | Vérifiez explicitement None avant de transmettre le résultat à decrypt_aes_cbc |
Annotation.generate_appearance renvoie False | Le sous-type de l’annotation n’a pas de synthétiseur d’apparence intégré (par exemple Text ou Popup) | Fournissez vos propres octets appearance_normal, ou acceptez le rendu par défaut du visualiseur |
Un deuxième appel à Document.generate_appearances renvoie 0 | L’appel est idempotent — les annotations qui possèdent déjà has_appearance == True sont ignorées | Comportement attendu, pas une erreur |
FAQ
Dois-je importer depuis aspose_pdf.engine pour le traitement quotidien des documents ?
Non. Les classes Document, Page et Annotation couvrent les flux de travail standard des documents. La couche moteur est l’endroit où le comportement de ces classes est implémenté, et elle est la plus utile pour les outils personnalisés ou l’inspection directe des internes du PDF.
Quelle est la différence entre Annotation.generate_appearance et AnnotationCollection.generate_appearances?
Le premier synthétise un flux d’apparence pour une annotation unique et renvoie un bool. Le second fait de même pour chaque annotation admissible dans une collection (les annotations d’une page, ou, via Document.generate_appearances, chaque page du document) et renvoie le nombre d’apparences qu’il a créées.
Pourquoi les méthodes de dérivation de clé prennent-elles un argument revision?
Le gestionnaire de sécurité du standard PDF a évolué au fil des révisions de la norme ISO 32000 — la révision 2 utilise le RC4 à 40 bits, les révisions 3/4 supportent le RC4 à 128 bits ou l’AES, et les révisions 5/6 (utilisées pour AES-256) utilisent un algorithme de hachage entièrement différent (compute_hash_v5). L’argument revision sélectionne quelle dérivation les méthodes EncryptionUtils effectuent.
Puis-je inspecter ou construire des objets PDF bruts directement?
Oui. aspose_pdf.engine.cos expose le modèle d’objet COS — PdfObject, PdfDictionary, PdfArray, PdfStream, PdfName et les types associés — que PdfCosWriter et PdfCosParser sérialisent en octets PDF et analysent à partir de ceux-ci.
Où se produit le rendu page-vers-image?
Document.render_page renvoie un RasterizedPage, un objet au niveau du moteur avec les méthodes to_png(), to_tiff() et save() pour transformer une page rendue en fichier image.
API Reference Résumé
| Classe / Méthode | Description |
|---|---|
Annotation.generate_appearance(force) -> bool | Synthétiser le flux d’apparence normal pour une annotation à la demande |
AnnotationCollection.generate_appearances(force) -> int | Générer en lot les apparences pour chaque annotation éligible sur une page |
Document.generate_appearances(force) -> int | Générer en lot les apparences pour chaque annotation éligible dans le document |
Document.flatten() -> Document | Intégrer les apparences d’annotation dans le contenu de la page et supprimer les annotations |
Document.render_page(page_index, dpi, scale, background, antialias) -> RasterizedPage | Rasteriser une page à travers le pipeline de rendu du moteur |
RasterizedPage | Une page rendue au format RGB empaqueté, avec to_png(), to_tiff() et save() |
GeneratedAppearance | Résultat interne de la synthèse d’apparence : octets de contenu plus toutes les ressources ExtGState/font requises |
EncryptionUtils | Chiffrement AES-CBC/RC4 et dérivation de clé du standard-security-handler PDF (Révisions 2–6) |
PdfObject | Classe de base abstraite pour chaque objet COS (Carousel Object Structure) |
PdfDictionary / PdfArray / PdfStream | Types de conteneurs COS concrets qui composent l’arbre de document de bas niveau |
PdfName / PdfNumber / PdfString / PdfBoolean / PdfNull | Types de valeurs COS primitives |
PdfIndirectReference | Une référence indirecte COS (n g R) vers un autre objet |
PdfCosWriter | Sérialise un COS PdfDocument en mémoire en octets PDF |
PdfCosParser / LazyPdfObjectStore | Analyse les octets PDF en objets COS, les matérialisant à la demande |
IncrementalUpdate / IncrementalWriter | Ajoute une section de mise à jour incrémentielle à un PDF existant au lieu de le réécrire |
SimplePdf | La représentation native-Python bas-niveau du document sur laquelle le Document API de haut niveau est construit |
TextFragmentAbsorber / TextFragmentCollection | Extraction de fragments de texte de bas niveau sur une instance SimplePdf |
ImagePlacementAbsorber / ImagePlacement | Localiser, enregistrer, remplacer ou masquer les images matricielles placées sur une page |
SigningUtils | Générer des certificats auto-signés et des signatures PKCS#7/CAdES pour la signature numérique |
DssMaterial / ChainResult / RevocationResult / TimestampInfo | Prise en charge de la validation des signatures : matériel DSS, résultats de chaîne de certificats, vérifications de révocation et validation des horodatages RFC 3161 |
StandardFonts | Métriques et encodages pour les 14 polices standard PDF |
CidTextCodec | Encoder et décoder les show-strings pour les polices composites (Type0) |
Shading | Échantillonner la couleur RGB sur les dégradés axiaux, radiaux et basés sur des fonctions |
Color / Matrix | Primitives de couleur de bas niveau et de transformation affine 2-D utilisées dans tout le moteur |