Управление документами
Управление документами
Класс 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-based индексацией — см. Распространённые проблемы ниже.
Шифрование и безопасность документов
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 из ненадёжного источника (загрузки, вложения электронной почты, веб-скрейпы); значения по умолчанию щедрые, но конечные, и не являются границей безопасности, на которую следует слепо полагаться. - Отлавливайте
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 и PdfFileEditor | doc.pages[i] начинается с нуля; аргументы страниц PdfFileEditor.extract()/.insert() начинаются с единицы | Добавляйте или вычитайте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 |
См. также:
- API Reference: Полная документация классов и методов для
aspose_pdf - База знаний: Ориентированные на задачу руководства «как сделать»
- Обзор продукта: Сводка функций и возможностей
- Начало работы / Установка: установка и настройка
- Aspose.PDF for Python — Enterprise Documentation