פרטים פנימיים של מנוע עיבוד PDF

פרטים פנימיים של מנוע עיבוד 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())  # 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 איננו מכיל יותר את ההערה השטוחה.


גזירת מפתחות הצפנה מבוססי סיסמה (גרסה 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 דו-ממדית המשמשים בכל המנוע

ראה גם

 עברית