مدیریت اسناد

مدیریت اسناد

مدیریت اسناد

کلاس Document نقطه ورودی تقریباً تمام عملیات‌ها در Aspose.PDF FOSS برای Python است: ایجاد یک PDF جدید، بارگذاری یک PDF موجود، ویرایش صفحات آن و نوشتن نتیجه به فایل. این راهنما چرخه حیات سند، عملیات‌های مجموعه صفحات، بهینه‌سازی، جریان‌های کاری چندفایلی، رمزنگاری و استثناهایی که باید انتظار پردازش آن‌ها را داشته باشید را مرور می‌کند.


چرخه حیات سند: ایجاد، باز کردن، و ذخیره

Document() بدون آرگومان یک سند خالی در حافظه ایجاد می‌کند. به عنوان اولین آرگومان مسیر فایل، bytes خام، یا هر جریان باینری قابل خواندن را پاس کنید (یا به‌طور صریح load_from() را فراخوانی کنید) تا به‌جای آن یک PDF موجود را بارگذاری کنید. save() یک مسیر یا یک جریان باینری قابل نوشتن مانند io.BytesIO را می‌پذیرد.

from aspose_pdf import Document

# Create a new, empty document and add a blank page
doc = Document()
doc.pages.add()
doc.save("hello.pdf")

# Re-open it — a path, bytes, or a binary stream all work
reopened = Document("hello.pdf")
print(reopened.page_count)   # 1

# ...or load explicitly onto an existing instance
another = Document()
another.load_from("hello.pdf")

reopened.close()
another.dispose()
doc.dispose()

save() اگر مسیر مقصد از پیش وجود داشته باشد، FileExistsError را ایجاد می‌کند، مگر اینکه overwrite=True را پاس کنید. close() یک نام مستعار برای dispose() است؛ هر دو ایدمپوتنت هستند، بنابراین فراخوانی آن‌ها بیش از یک‌بار ایمن است.

فقط PDF به‌عنوان هدف ذخیره پیاده‌سازی شده است — این بخش اصلی کتابخانه و یک عملکرد کاملاً کارا است. ارسال یک مقدار خروجی مانند SaveFormat.PPTX یا DocFormat.HTML به save() باعث ایجاد UnsupportedFeatureException می‌شود به‌جای نوشتن فایلی با نام نادرست، بنابراین یک خروجی ناموفق همیشه به‌صورت واضح (خطا) اعلام می‌شود نه به‌صورت ساکت.


مدیریت مجموعه صفحات

doc.pages یک PageCollection است. از len()، تکرار و ایندکس‌گذاری صفر-پایه (doc.pages[0]) پشتیبانی می‌کند، به علاوه add()، insert(index, page) و delete(index) برای ویرایش‌های ساختاری. هر Page، index، rect (یعنی MediaBox) و rotation را نمایش می‌دهد.

from aspose_pdf import Document

doc = Document()
doc.pages.add()            # page 0
doc.pages.add()            # page 1
doc.pages.insert(1, None)  # insert a blank page at index 1

print(doc.page_count)      # 3

first_page = doc.pages[0]
print(first_page.rect)     # (0, 0, 612, 792)

for page in doc.pages:
    print(page.index, page.rotation)

doc.pages.delete(1)        # remove the page we inserted
doc.save("pages_demo.pdf", overwrite=True)

pages.add(page=None) یک صفحه خالی اضافه می‌کند وقتی بدون آرگومان فراخوانی شود. pages.insert() ایندکس خارج از بازه را به نزدیک‌ترین موقعیت معتبر محدود می‌کند به جای اینکه خطا بدهد.


بهینه‌سازی و فشرده‌سازی اسناد

Document.optimize در یک فراخوانی حذف تکرار تصویر/جریان، جمع‌آوری زباله اشیاء استفاده‌نشده و فشرده‌سازی جریان را اجرا می‌کند. برای کنترل تکنیک‌های اجرا شده یک نمونه OptimizationOptions پاس دهید؛ اگر آن را حذف کنید از پروفایل پاک‌سازی استاندارد استفاده می‌شود.

from aspose_pdf import Document, OptimizationOptions

doc = Document("large_report.pdf")

options = OptimizationOptions()
options.remove_unused_objects = True
options.link_duplicate_streams = True
options.image_compression_quality = 60
options.subset_fonts = True

doc.optimize(options)
doc.save("large_report_optimized.pdf", overwrite=True)

optimize_resources() یک نام مستعار برای optimize() است. اگر فقط فشرده‌سازی جریان را بدون عبور پاک‌سازی ساختاری می‌خواهید، مستقیماً doc.compress_streams() را صدا بزنید.


ادغام، تقسیم و ویرایش فایل‌ها

برای اسنادی که از قبل باز دارید، Document.merge() نمونه‌های دیگر Document را به نمونهٔ فعلی اضافه می‌کند:

from aspose_pdf import Document

base = Document("part1.pdf")
extra = Document("part2.pdf")

base.merge(extra)
base.save("combined.pdf", overwrite=True)

برای جریان‌های کاری فایل-به-فایل بدون اینکه خودتان یک Document باز کنید، افزونه‌های کم‌کد Merger و Splitter یک شیء MergeOptions/SplitOptions که از ورودی‌ها و خروجی‌های FileDataSource ساخته شده است، می‌گیرند:

from aspose_pdf import Merger, MergeOptions, Splitter, SplitOptions, FileDataSource

# Merge two files into one
merge_options = MergeOptions()
merge_options.add_input(FileDataSource("part1.pdf"))
merge_options.add_input(FileDataSource("part2.pdf"))
merge_options.add_output(FileDataSource("combined.pdf"))
Merger().process(merge_options)

# Split the result into one file per page
split_options = SplitOptions()
split_options.add_input(FileDataSource("combined.pdf"))
split_options.add_output(FileDataSource("combined_page1.pdf"))
split_options.add_output(FileDataSource("combined_page2.pdf"))
Splitter().process(split_options)

PdfFileEditor همان مجموعه‌ای از عملیات را به عنوان یک واسط ارائه می‌دهد که به جای پرتاب استثنا، True/False را برمی‌گرداند، که برای اسکریپت‌های دسته‌ای مناسب است:

from aspose_pdf import PdfFileEditor

with PdfFileEditor() as editor:
    ok = editor.concatenate(["part1.pdf", "part2.pdf"], "combined.pdf")
    if not ok:
        print("concatenate failed:", editor.last_exception)

    editor.extract("combined.pdf", "first_page_only.pdf", page_from=1, page_to=1)

PdfFileEditor.extract() and .insert() take مبتنی بر ۱ شماره‌های صفحه، برخلاف PageCollectionشاخص صفر پایه — ببینید مشکلات رایج در زیر.


رمزنگاری و امنیت سند

Document.encrypt(user_password, owner_password=None, permissions=-4) سند در-حافظه را رمزنگاری می‌کند؛ decrypt(password) و change_passwords(old, new_user, new_owner=None) رمزها را معکوس یا چرخش می‌دهند. is_encrypted و permissions وضعیت فعلی را گزارش می‌دهند.

from aspose_pdf import Document
from aspose_pdf.exceptions import PdfSecurityException

doc = Document()
doc.pages.add()
doc.encrypt("user-pass", "owner-pass", permissions=-4)
doc.save("secured.pdf", overwrite=True)

try:
    Document("secured.pdf", password="wrong-pass")
except PdfSecurityException as exc:
    print("could not open:", exc)

reopened = Document("secured.pdf", password="user-pass")
print(reopened.is_encrypted)   # True
reopened.decrypt("user-pass")
reopened.save("unsecured.pdf", overwrite=True)

باز کردن یک سند رمزنگاری‌شده بدون رمز عبور، یا با رمز نادرست، PdfSecurityException را پرتاب می‌کند — به جای فرض اینکه بارگذاری همیشه موفق باشد، این کلاس (از aspose_pdf.exceptions) را دریافت کنید.


متادیتا، اعتبارسنجی و مدیریت استثنا

متادیتای سند در doc.info قرار دارد (یک dict[str, str] ساده)، و doc.version / doc.id نسخهٔ سرآیند PDF و شناسهٔ فایل تریلر را نشان می‌دهند. validate() (که به عنوان check() شناخته می‌شود) یکپارچگی ساختاری را گزارش می‌کند؛ repair() سعی می‌کند مشکلات رایجی مانند فهرست صفحات گمشده یا MediaBox خارج از محدوده را برطرف کند.

from aspose_pdf import Document, PdfLoadLimits
from aspose_pdf.exceptions import AsposePdfException, PdfIOException

doc = Document()
doc.pages.add()
doc.info["Title"] = "Quarterly Report"
doc.info["Author"] = "Reporting Bot"
doc.save("report.pdf", overwrite=True)

# Load untrusted input under an explicit resource-limit policy
safe_limits = PdfLoadLimits(max_input_bytes=50 * 1024 * 1024, max_pages=1000)

try:
    untrusted = Document("incoming.pdf", limits=safe_limits)
    if not untrusted.validate():
        untrusted.repair()
except (AsposePdfException, PdfIOException) as exc:
    print("failed to process incoming.pdf:", exc)

PdfLoadLimits حافظه و تعداد اشیا را برای فایل‌های غیرقابل اعتماد محدود می‌کند؛ برای غیرفعال‌سازی تمام محدودیت‌ها وقتی منبع را کاملاً اعتماد دارید، PdfLoadLimits.unlimited() را فراخوانی کنید. AsposePdfException کلاس پایه برای کل سلسله‌مراتب استثناها است (از جمله PdfIOException و PdfSecurityException)، بنابراین یک except AsposePdfException واحد هر خطای ایجادشده توسط کتابخانه را می‌گیرد.


نکات و بهترین شیوه‌ها

  • همواره dispose() (یا close()) را بر روی Document فراخوانی کنید زمانی که کارتان با آن تمام شد، یا آن را به‌عنوان یک متغیر محلی کوتاه‌مدت استفاده کنید — موتور محتوای صفحه و تصاویر رمزگشایی‌شده را تا زمان حذف در حافظه نگه می‌دارد.
  • هنگام بازنویسی مسیری که قبلاً در همان اجرا ایجاد کرده‌اید، overwrite=True را به save() بدهید؛ مقدار پیش‌فرض False است و FileExistsError را برمی‌انگیزد.
  • قبل از انتشار یک PDF تولید‌شده، از doc.optimize() استفاده کنید — این یک فراخوانی تک‌بار است که اشیای استفاده‌نشده را حذف می‌کند و جریان‌ها را فشرده می‌سازد و معمولاً اندازه خروجی را به‌طور قابل‌مشاهده‌ای کاهش می‌دهد.
  • همیشه به‌صورت صریح یک سیاست PdfLoadLimits تنظیم کنید هر زمان که PDFها را از منبعی غیرقابل اعتماد (بارگذاری‌ها، پیوست‌های ایمیل، استخراج‌های وب) بارگذاری می‌کنید؛ مقادیر پیش‌فرض بخشنده اما محدود هستند و مرز امنیتی نیستند که به‌صورت کورکورانه به آن اعتماد کنید.
  • به‌جای Exception خالص، AsposePdfException (یا یک زیرکلاس خاص مانند PdfSecurityException) را در اطراف فراخوانی‌های بارگذاری/ذخیره‌سازی بگیرید — این پایهٔ مشترک برای تمام خطاهایی است که کتابخانه برمی‌انگیزد.

مشکلات رایج

مشکلدلیلرفع
FileExistsError روی save()مسیر مقصد از پیش موجود است و overwrite در مقدار پیش‌فرض False باقی مانده استارسال save(path, overwrite=True)
UnsupportedFeatureException روی save()یک save_format غیر PDF (به عنوان مثال SaveFormat.PPTX، DocFormat.HTML) درخواست شدذخیره به‌عنوان PDF — هر مقدار دیگر SaveFormat/DocFormat باعث ایجاد UnsupportedFeatureException می‌شود به‌جای نوشتن خروجی
PdfSecurityException: Password required for encrypted documentPDF رمزگذاری‌شده بدون آرگومان password باز شدمقدار Document(path, password="...") را ارسال کنید یا load_from(path, password="...") را فراخوانی کنید
اختلاف یک عدد صفحه بین PageCollection و PdfFileEditordoc.pages[i] مبتنی بر صفر است؛ آرگومان‌های صفحه PdfFileEditor.extract()/.insert() مبتنی بر یک هستندهنگام تبدیل بین دو API، ۱ را اضافه یا کم کنید
IndexError: Page index out of range. از pages.delete()نمایه‌ ارسال‌شده به delete() در مجموعه وجود نداردقبل از حذف، doc.page_count (یا len(doc.pages)) را بررسی کنید

FAQ

آیا برای استفاده از Aspose.PDF FOSS برای Python به مجوز نیاز دارم؟

خیر. این نسخه متن باز (دارای مجوز MIT) است؛ هیچ فایل مجوز یا مرحلهٔ فعال‌سازی برای پیکربندی وجود ندارد.

آیا می‌توانم یک Document را به فرمت‌های دیگری غیر از PDF صادر کنم؟

در این نسخه امکان‌پذیر نیست. save() فقط خروجی PDF را پیاده‌سازی می‌کند — ارسال مقدار دیگری از نوع SaveFormat/DocFormat منجر به بروز UnsupportedFeatureException می‌شود و فایل اشتباه‌برچسب‌گذاری‌شده‌ای تولید نمی‌کند.

تفاوت بین Document.merge() و افزونهٔ Merger چیست؟

Document.merge() نمونه‌های Document را که قبلاً در حافظه باز کرده‌اید ترکیب می‌کند. Merger (با MergeOptions و FileDataSource) یک بستهٔ راحتی فایل-به-فایل است که در یک فراخوانی برای شما باز می‌کند، ترکیب می‌کند و ذخیره می‌کند — برای اسکریپت‌های سادهٔ دسته‌ای که هرگز به شیء میانی Document نیاز ندارند، مفید است.

چرا pages.insert() هرگز برای اندیسی خارج از محدوده خطا نمی‌دهد؟

PageCollection.insert() اندیس را به محدودهٔ معتبر محدود می‌کند (مقدارهای منفی به 0 تبدیل می‌شوند، مقادیر بیش از انتها به len(doc.pages)) به‌جای این‌که خطا بدهد، بنابراین درج به‌خاطر مقدار اندیس به‌تنهایی هرگز شکست نمی‌خورد.

چگونه می‌توانم یک PDF را به‌صورت ایمن از منبع غیرقابل اعتماد بارگذاری کنم؟

یک PdfLoadLimits را با محدودیت‌های صریح (max_input_bytes، max_pages، max_objects و غیره) بسازید و آن را به‌عنوان آرگومان limits= به Document(...) یا load_from() پاس دهید. هر فیلد به‌طور پیش‌فرض مقدار محدودی دارد، اما محدود کردن آن‌ها به اندازه ورودی مورد انتظار، منابع مصرفی یک فایل خراب‌شده را کاهش می‌دهد.


خلاصه API Reference

کلاس / متدتوضیح
Document() / Document.load_fromیک سند خالی ایجاد کنید یا آن را از مسیر، بایت‌ها یا یک جریان باینری بارگذاری کنید
Document.saveسند را در یک مسیر یا جریان قابل نوشتن بنویسید (فقط PDF)
Document.dispose() / Document.close()منابع موتور را آزاد کنید؛ بدون اثر تکراری
Document.pagesPageCollection سند
Document.infoمتادیتای سند به عنوان یک dict[str, str]
Document.optimize / Document.optimize_resources / Document.compress_streams()حذف منابع استفاده‌نشده و فشرده‌سازی جریان‌ها
Document.merge()نمونه‌های دیگر Document را به این مورد اضافه کنید
Document.encrypt / Document.decrypt / Document.change_passwordsاعمال، حذف یا چرخاندن گذرواژه‌های سند
Document.validate() / Document.check() / Document.repair()بررسی و تلاش برای رفع یکپارچگی ساختاری
PageCollection.add() / .insert() / .delete() / .item()ویرایش‌های ساختاری مجموعه صفحات (صفر مبنا)
Page.rect / Page.rotation / Page.indexهندسه و موقعیت هر صفحه
OptimizationOptionsپرچم‌های دقیق‌الگویی که توسط Document.optimize مصرف می‌شوند
MergeOptions / Mergerافزونهٔ ادغام فایل-به-فایل
SplitOptions / Splitterافزونهٔ تقسیم فایل-به-فایل یک-صفحه-در-هر-خروجی
FileDataSourceورودی/خروجی مبتنی بر فایل برای APIهای افزونه
PdfFileEditorرابط جلویی برای concatenate()، extract()، insert()، delete()، append() (صفحات با شماره‌گذاری از ۱)
PdfLoadLimitsسیاست محدودیت منابع غیرقابل تغییر برای ورودی‌های نامطمئن
AsposePdfExceptionکلاس پایه برای هر استثنایی که کتابخانه برمی‌انگیزد
PdfSecurityExceptionدر صورت عدم وجود یا نادرست بودن رمز عبور و خطاهای دسترسی برانگیخته می‌شود
PdfIOExceptionدر صورت بروز خطاهای ورودی/خروجی هنگام پردازش PDF برانگیخته می‌شود

همچنین ببینید:

 فارسی