פרטים פנימיים של מנוע עיבוד PDF
פנימיות מנוע עיבוד 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 איננו מכיל יותר את ההערה השטוחה.
גזירת מפתחות הצפנה מבוססי סיסמה (גרסה 4 / AES-128)
EncryptionUtils מיישם ישירות את גזירת המפתחות של מטפל האבטחה של תקן PDF ואת הפרימיטיבים של AES-CBC, באופן עצמאי מה-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 (RC4/AES של 40 ו-128 ביט), בעוד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 התפתח לאורך גרסאות ISO32000 — גרסה2 משתמשת ב-RC4 של 40-ביט, גרסאות3/4 תומכות ב-RC4 של 128-ביט או AES, וגרסאות5/6 (בשימוש עבור AES-256) משתמשות באלגוריתם hashing שונה לחלוטין (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 standard-security-handler (גרסאות 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 | הייצוג ברמת-הנמוכה native-Python של המסמך שעליו נבנה ה-Document API ברמה גבוהה |
TextFragmentAbsorber / TextFragmentCollection | חילוץ קטעי טקסט ברמת נמוכה על מופע של SimplePdf |
ImagePlacementAbsorber / ImagePlacement | לאתר, לשמור, להחליף, או להסתיר תמונות רסטר המוצבות בדף |
SigningUtils | יצירת תעודות חתימה עצמית וחתימות PKCS#7/CAdES לחתימה דיגיטלית |
DssMaterial / ChainResult / RevocationResult / TimestampInfo | תמיכת אימות חתימות: חומר DSS, תוצאות שרשרת תעודות, בדיקות ביטול, ואימות חותמת זמן RFC 3161 |
StandardFonts | מדדים וקידודים ל-14 גופני PDF סטנדרטיים |
CidTextCodec | קידוד ופענוח של show-strings עבור גופנים מורכבים (Type0) |
Shading | דוגמת צבע RGB על פני הצללות אקסיאליות, רדיאליות והמבוססות על פונקציות |
Color / Matrix | פרימיטיבים של צבע ברמת נמוכה והמרת affine-transform דו-ממדית המשמשים בכל המנוע |