الداخلية لمحرك معالجة 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() يرسم مظهر كل تعليق توضيحي مباشرةً في تدفق محتوى الصفحة (كمستدعي كائن XObject Do) ثم يزيل كائن التعليق نفسه، بحيث تُعرض الصفحة بصورة متطابقة في عارضات تتجاهل التعليقات التوضيحية تمامًا:
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-bit و128-bit)، بينما يطبقcompute_hash_v5الخوارزمية للإصدار 5/6 المستخدمة من قبل AES-256. خلط الإصدارات وطول المفاتيح ينتج مفتاحًا خاطئًا بصمت. Document.generate_appearancesوAnnotationCollection.generate_appearancesمتطابقتان (idempotent) — استدعِهما بحذر قبل عرض أو تسطيح مستند لم تقم بإنشائه بنفسك.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 | الاستدعاء idempotent — يتم تخطي التعليقات التوضيحية التي لديها بالفعل 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 يستخدم RC4 بحد 40-بت، والإصدارين 3/4 يدعمان RC4 بحد 128-بت أو 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 | يقوم بتسلسل PdfDocument من نوع COS في الذاكرة إلى بايتات PDF |
PdfCosParser / LazyPdfObjectStore | يحلّل بايتات PDF إلى كائنات COS، ويُنشئها عند الطلب |
IncrementalUpdate / IncrementalWriter | إلحاق قسم تحديث تدريجي إلى ملف PDF موجود بدلاً من إعادة كتابته |
SimplePdf | تمثيل المستند منخفض المستوى الأصلي-Python الذي يُبنى عليه Document API عالي المستوى |
TextFragmentAbsorber / TextFragmentCollection | استخراج مقاطع نصية منخفضة المستوى على مثيل SimplePdf |
ImagePlacementAbsorber / ImagePlacement | تحديد، حفظ، استبدال أو إخفاء الصور النقطية الموجودة على صفحة |
SigningUtils | إنشاء شهادات موقعة ذاتيًا وتواقيع PKCS#7/CAdES للتوقيع الرقمي |
DssMaterial / ChainResult / RevocationResult / TimestampInfo | دعم التحقق من التواقيع: مواد DSS، نتائج سلسلة الشهادات، فحوصات الإلغاء، والتحقق من طوابع الوقت وفق RFC 3161 |
StandardFonts | القياسات والترميزات للخطوط القياسية الـ14 في PDF |
CidTextCodec | ترميز وفك ترميز سلاسل العرض للخطوط المركبة (Type0) |
Shading | عينة لون RGB عبر التظليل المحوري، الشعاعي، وتظليل القائم على الدوال |
Color / Matrix | بدائيات اللون وتحويل الأفيـن ثنائي الأبعاد منخفضة المستوى المستخدمة في جميع أرجاء المحرك |