Керування документами

Керування документами

Управління документами

Клас Document є точкою входу майже для всіх операцій у Aspose.PDF FOSS для Python: створення нового 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 вручну, low-code плагіни 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 нумерація з 1 номери сторінок, на відміну від PageCollectionнумерація з 0 — дивіться Поширені проблеми нижче.


Шифрування та безпека документів

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.
  • Віддавайте перевагу doc.optimize() перед випуском згенерованого PDF — це один виклик, який видаляє невикористані об’єкти та стискає потоки, і зазвичай помітно зменшує розмір вихідного файлу.
  • Встановлюйте політику PdfLoadLimits явно щоразу, коли завантажуєте PDF з ненадійного джерела (завантаження, email-вкладення, веб-збірка); типові значення щедрі, але обмежені, і не є безпековою межою, на яку слід сліпо покладатися.
  • Перехоплюйте AsposePdfException (або конкретний підклас, наприклад PdfSecurityException) навколо викликів завантаження/збереження, а не просто Exception — це спільна база для будь-якої помилки, яку генерує бібліотека.

Типові проблеми

ПроблемаПричинаВиправлення
FileExistsError на save()Шлях призначення вже існує, і overwrite залишено зі значенням за замовчуванням FalseПропустити save(path, overwrite=True)
UnsupportedFeatureException на save()Запитано не-PDF save_format (наприклад, SaveFormat.PPTX, DocFormat.HTML)Зберегти як PDF — будь-яке інше значення SaveFormat/DocFormat викликає UnsupportedFeatureException замість запису вихідних даних
PdfSecurityException: Password required for encrypted documentВідкрито зашифрований PDF без аргументу passwordПередайте Document(path, password="...") або викличте load_from(path, password="...")
Відхилення на один у номерах сторінок між PageCollection і PdfFileEditordoc.pages[i] індексується з нуля; аргументи сторінок PdfFileEditor.extract()/.insert() — з 1Додавайте або віднімайте 1 при перетворенні між двома 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.pagesЗначення PageCollection документа
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() (сторінки, нумерація з 1)
PdfLoadLimitsНезмінна політика обмежень ресурсів для ненадійного вводу
AsposePdfExceptionБазовий клас для всіх виключень, які піднімає бібліотека
PdfSecurityExceptionВикликається при відсутності/некоректних паролях та помилках доступу
PdfIOExceptionВикликається при помилках вводу/виводу під час обробки PDF

Дивіться також

 Українська