Gerenciamento de Documentos

Gerenciamento de Documentos

Gerenciamento de Documentos

A classe Document é o ponto de entrada para quase todas as operações no Aspose.PDF FOSS para Python: criar um novo PDF, carregar um existente, editar suas páginas e gravar o resultado. Este guia percorre o ciclo de vida do documento, as operações de coleção de páginas, otimização, fluxos de trabalho multi-arquivo, criptografia e as exceções que você deve esperar tratar.


Ciclo de Vida do Documento: Criar, Abrir e Salvar

Document() sem argumentos cria um documento vazio na memória. Passe um caminho de arquivo, bytes cru, ou qualquer fluxo binário legível como primeiro argumento (ou chame load_from() explicitamente) para carregar um PDF existente. save() aceita um caminho ou um fluxo binário gravável, como 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() gera FileExistsError se o caminho de destino já existir, a menos que você passe overwrite=True. close() é um alias para dispose(); ambos são idempotentes, portanto chamá-los mais de uma vez é seguro.

Somente PDF está implementado como destino de salvamento — esta é a funcionalidade central da biblioteca, totalmente operacional. Passar um valor de exportação como SaveFormat.PPTX ou DocFormat.HTML para save() gera UnsupportedFeatureException em vez de gravar um arquivo rotulado incorretamente, portanto uma exportação falha é sempre evidente, não silenciosa.


Gerenciando a Coleção de Páginas

doc.pages é um PageCollection. Ele suporta len(), iteração e indexação baseada em zero (doc.pages[0]), além de add(), insert(index, page) e delete(index) para edições estruturais. Cada Page expõe index, rect (o MediaBox) e 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) adiciona uma página em branco quando chamado sem argumento. pages.insert() limita um índice fora do intervalo à posição válida mais próxima em vez de lançar.


Otimização e Compactação de Documentos

Document.optimize executa deduplicação de imagem/fluxo, coleta de lixo de objetos não usados e compressão de fluxo em uma única chamada. Passe uma instância de OptimizationOptions para controlar quais técnicas são executadas; omita-a para usar o perfil de limpeza padrão.

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() é um alias para optimize(). Se você quiser apenas compressão de fluxo sem a etapa de limpeza estrutural, chame doc.compress_streams() diretamente.


Mesclagem, Divisão e Edição de Arquivos

Para documentos que você já tem abertos, Document.merge() adiciona outras instâncias de Document ao documento atual:

from aspose_pdf import Document

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

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

Para fluxos de trabalho file-to-file sem abrir um Document por conta própria, os plugins low-code Merger e Splitter recebem um objeto MergeOptions/SplitOptions construído a partir das entradas e saídas de 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 oferece a mesma família de operações como uma fachada que retorna True/False em vez de lançar exceções, o que é conveniente para scripts em lote:

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 baseado em 1 números de página, ao contrário PageCollectionindexação baseada em 0 — veja Problemas comuns abaixo.


Criptografia e Segurança de Documentos

Document.encrypt(user_password, owner_password=None, permissions=-4) criptografa o documento em memória; decrypt(password) e change_passwords(old, new_user, new_owner=None) invertem ou rotacionam senhas. is_encrypted e permissions relatam o estado atual.

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)

Abrir um documento criptografado sem senha, ou com a senha errada, gera PdfSecurityException — capture esta classe (de aspose_pdf.exceptions) em vez de supor que o carregamento sempre terá sucesso.


Metadados, Validação e Tratamento de Exceções

Os metadados do documento residem em doc.info (um simples dict[str, str]), e doc.version / doc.id expõem a versão do cabeçalho PDF e o identificador do arquivo trailer. validate() (apelidado como check()) relata a integridade estrutural; repair() tenta corrigir problemas comuns como uma lista de páginas ausente ou um MediaBox fora do intervalo.

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 limita a memória e a contagem de objetos para arquivos não confiáveis; chame PdfLoadLimits.unlimited() para desativar todos os limites quando você confia totalmente na fonte. AsposePdfException é a classe base para toda a hierarquia de exceções (incluindo PdfIOException e PdfSecurityException), portanto um único except AsposePdfException captura qualquer erro gerado pela biblioteca.


Dicas e Melhores Práticas

  • Sempre chame dispose() (ou close()) em um Document quando terminar com ele, ou use-o como uma variável local de curta duração — o motor mantém o conteúdo da página decodificado e as imagens na memória até a liberação.
  • Passe overwrite=True para save() ao reescrever um caminho que você já criou na mesma execução; o padrão é False e gera FileExistsError.
  • Prefira doc.optimize() antes de distribuir um PDF gerado — é uma chamada única que remove objetos não usados e comprime fluxos, e normalmente reduz o tamanho da saída de forma perceptível.
  • Defina uma política de PdfLoadLimits explicitamente sempre que carregar PDFs de uma fonte não confiável (envios, anexos de e-mail, raspagens da web); os padrões são generosos, porém limitados, não constituindo uma barreira de segurança na qual você deva confiar cegamente.
  • Capture AsposePdfException (ou uma subclasse específica, como PdfSecurityException) ao redor de chamadas de carga/gravação, em vez de Exception puro — ela é a base comum para todos os erros que a biblioteca gera.

Problemas Comuns

ProblemaCausaCorreção
FileExistsError em save()O caminho de destino já existe e overwrite foi deixado no seu padrão FalsePassar save(path, overwrite=True)
UnsupportedFeatureException em save()Um save_format não PDF (por exemplo, SaveFormat.PPTX, DocFormat.HTML) foi solicitadoSalvar como PDF — qualquer outro valor de SaveFormat/DocFormat gera UnsupportedFeatureException em vez de gravar a saída
PdfSecurityException: Password required for encrypted documentUm PDF criptografado foi aberto sem um argumento passwordPasse Document(path, password="...") ou chame load_from(path, password="...")
Números de página fora de um entre PageCollection e PdfFileEditordoc.pages[i] é baseado em zero; os argumentos de página PdfFileEditor.extract()/.insert() são baseados em umAdicione ou subtraia 1 ao converter entre as duas APIs
IndexError: Page index out of range. de pages.delete()O índice passado para delete() não existe na coleçãoVerifique doc.page_count (ou len(doc.pages)) antes de excluir

FAQ

Preciso de uma licença para usar Aspose.PDF FOSS para Python?

Não. Esta é a edição de código aberto (licenciada sob MIT); não há arquivo de licença nem etapa de ativação para configurar.

Posso exportar um Document para formatos diferentes de PDF?

Não nesta versão. save() implementa apenas saída em PDF — passar outro valor SaveFormat/DocFormat gera UnsupportedFeatureException em vez de produzir um arquivo com rótulo errado.

Qual é a diferença entre Document.merge() e o plugin Merger?

Document.merge() combina instâncias de Document que você já tem abertas na memória. Merger (com MergeOptions e FileDataSource) é um wrapper de conveniência file-to-file que abre, mescla e salva para você em uma única chamada — útil para scripts batch simples que nunca precisam do objeto intermediário Document.

Por que pages.insert() nunca gera um erro para um índice fora do intervalo?

PageCollection.insert() limita o índice ao intervalo válido (valores negativos tornam-se 0, valores além do fim tornam-se len(doc.pages)) em vez de gerar erro, portanto uma inserção nunca falha apenas por causa do valor do índice.

Como faço para carregar um PDF com segurança a partir de uma fonte não confiável?

Construa um PdfLoadLimits com limites explícitos (max_input_bytes, max_pages, max_objects e assim por diante) e passe-o como o argumento limits= para Document(...) ou load_from(). Cada campo já tem um valor finito padrão, mas restringi-los ao tamanho de entrada esperado reduz os recursos que um arquivo malformado pode consumir.


API Reference Resumo

Classe / MétodoDescrição
Document() / Document.load_fromCrie um documento vazio ou carregue um a partir de um caminho, bytes ou um fluxo binário
Document.saveEscreva o documento em um caminho ou em um fluxo gravável (apenas PDF)
Document.dispose() / Document.close()Libere os recursos do motor; idempotente
Document.pagesO PageCollection do documento
Document.infoMetadados do documento como um dict[str, str]
Document.optimize / Document.optimize_resources / Document.compress_streams()Remover recursos não utilizados e comprimir fluxos
Document.merge()Acrescentar outras instâncias de Document a esta
Document.encrypt / Document.decrypt / Document.change_passwordsAplicar, remover ou girar senhas de documento
Document.validate() / Document.check() / Document.repair()Verificar e tentar corrigir a integridade estrutural
PageCollection.add() / .insert() / .delete() / .item()Edições estruturais da coleção de páginas (base zero)
Page.rect / Page.rotation / Page.indexGeometria e posição por página
OptimizationOptionsFlags de granularidade fina consumidas por Document.optimize
MergeOptions / MergerPlugin de mesclagem de arquivo para arquivo
SplitOptions / SplitterPlugin de divisão de arquivo para arquivo, uma página por saída
FileDataSourceEntrada/saída baseada em arquivo para as APIs do plugin
PdfFileEditorFacade para concatenate(), extract(), insert(), delete(), append() (páginas baseadas em 1)
PdfLoadLimitsPolítica imutável de limite de recursos para entrada não confiável
AsposePdfExceptionClasse base para todas as exceções que a biblioteca gera
PdfSecurityExceptionGerada para senhas ausentes/incorretas e erros de permissão
PdfIOExceptionGerada para erros de E/S durante o processamento de PDF

Ver também

 Português