Gestione dei documenti
Gestione dei Documenti
La classe Document è il punto di ingresso per quasi tutte le operazioni in Aspose.PDF FOSS per Python: creare un nuovo PDF, caricare uno esistente, modificare le sue pagine e scrivere nuovamente il risultato. Questa guida percorre il ciclo di vita del documento, le operazioni sulla raccolta di pagine, l’ottimizzazione, i flussi di lavoro multi-file, la crittografia e le eccezioni che dovresti gestire.
Ciclo di vita del documento: Creare, Aprire e Salvare
Document() senza argomenti crea un documento vuoto in memoria. Passa un percorso file, raw bytes, o qualsiasi stream binario leggibile come primo argomento (oppure chiama load_from() esplicitamente) per caricare invece un PDF esistente. save() accetta un percorso o uno stream binario scrivibile come 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() solleva FileExistsError se il percorso di destinazione esiste già, a meno che non venga passato overwrite=True. close() è un alias per dispose(); entrambi sono idempotenti, quindi chiamarli più di una volta è sicuro.
Solo PDF è implementato come destinazione di salvataggio — questa è la funzione centrale della libreria, completamente funzionante. Passare un valore di esportazione come SaveFormat.PPTX o DocFormat.HTML a save() solleva UnsupportedFeatureException invece di scrivere un file etichettato in modo errato, quindi un’esportazione fallita è sempre evidente piuttosto che silenziosa.
Gestione della raccolta di pagine
doc.pages è un PageCollection. Supporta len(), l’iterazione e l’indicizzazione a base zero (doc.pages[0]), oltre a add(), insert(index, page) e delete(index) per modifiche strutturali. Ogni Page espone index, rect (il 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) aggiunge una pagina vuota quando viene chiamato senza argomento. pages.insert() limita un indice fuori intervallo alla posizione valida più vicina anziché generare un errore.
Ottimizzare e comprimere i documenti
Document.optimize esegue la deduplicazione di immagini/stream, la raccolta dei rifiuti di oggetti inutilizzati e la compressione dello stream in una sola chiamata. Fornisci un’istanza di OptimizationOptions per controllare quali tecniche vengono eseguite; omettila per utilizzare il profilo di pulizia standard.
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() è un alias di optimize(). Se desideri solo la compressione dello stream senza il passaggio di pulizia strutturale, chiama direttamente doc.compress_streams().
Unire, dividere e modificare i file
Per i documenti che hai già aperto, Document.merge() aggiunge altre istanze di Document a quella corrente:
from aspose_pdf import Document
base = Document("part1.pdf")
extra = Document("part2.pdf")
base.merge(extra)
base.save("combined.pdf", overwrite=True)Per i flussi di lavoro file-a-file senza aprire un Document da solo, i plugin low-code Merger e Splitter accettano un oggetto MergeOptions/SplitOptions costruito dagli input e output di 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 offre la stessa famiglia di operazioni come una facciata che restituisce True/False invece di generare un’eccezione, il che è comodo per gli script batch:
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 basato su 1 numeri di pagina, a differenza di PageCollectionindicizzazione a base 0 — vedi Problemi comuni di seguito.
Crittografia e sicurezza del documento
Document.encrypt(user_password, owner_password=None, permissions=-4) cifra il documento in memoria; decrypt(password) e change_passwords(old, new_user, new_owner=None) invertono o ruotano le password. is_encrypted e permissions segnalano lo stato attuale.
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)Aprire un documento crittografato senza password, o con quella errata, genera PdfSecurityException — intercetta questa classe (da aspose_pdf.exceptions) invece di presumere che il caricamento abbia sempre successo.
Metadati, convalida e gestione delle eccezioni
I metadati del documento risiedono su doc.info (un semplice dict[str, str]), e doc.version / doc.id espongono la versione dell’intestazione PDF e l’identificatore del file trailer. validate() (alias check()) segnala l’integrità strutturale; repair() tenta di correggere problemi comuni come una lista di pagine mancante o un MediaBox fuori intervallo.
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 la memoria e il conteggio degli oggetti per file non attendibili; chiama PdfLoadLimits.unlimited() per disabilitare tutti i limiti quando ti fidi completamente della sorgente. AsposePdfException è la classe base per l’intera gerarchia di eccezioni (inclusi PdfIOException e PdfSecurityException), quindi un unico except AsposePdfException cattura qualsiasi errore sollevato dalla libreria.
Suggerimenti e migliori pratiche
- Chiama sempre
dispose()(oclose()) su unDocumentquando hai finito di usarlo, oppure usalo come variabile locale a vita breve — il motore mantiene il contenuto delle pagine decodificate e le immagini in memoria fino allo smaltimento. - Passa
overwrite=Trueasave()quando riscrivi un percorso che hai già creato nella stessa esecuzione; il valore predefinito èFalsee generaFileExistsError. - Preferisci
doc.optimize()prima di distribuire un PDF generato — è una chiamata singola che rimuove gli oggetti inutilizzati e comprime i flussi, e di solito riduce notevolmente la dimensione dell’output. - Imposta esplicitamente una politica
PdfLoadLimitsogni volta che carichi PDF da una fonte non attendibile (caricamenti, allegati email, estrazioni web); i valori predefiniti sono generosi ma finiti, non rappresentano una barriera di sicurezza su cui fare affidamento ciecamente. - Gestisci
AsposePdfException(o una sottoclasse specifica comePdfSecurityException) intorno alle chiamate di caricamento/salvataggio invece di usare direttamenteException— è la base comune per ogni errore sollevato dalla libreria.
Problemi comuni
| Problema | Cause | Correzione |
|---|---|---|
FileExistsError su save() | Il percorso di destinazione esiste già e overwrite è stato lasciato al suo valore predefinito False | Passa save(path, overwrite=True) |
UnsupportedFeatureException su save() | È stato richiesto un save_format non-PDF (ad es. SaveFormat.PPTX, DocFormat.HTML) | Salva come PDF — qualsiasi altro valore SaveFormat/DocFormat solleva UnsupportedFeatureException invece di scrivere l’output |
PdfSecurityException: Password required for encrypted document | Aperto un PDF crittografato senza l’argomento password | Passa Document(path, password="...") o chiama load_from(path, password="...") |
Errore di uno nei numeri di pagina tra PageCollection e PdfFileEditor | doc.pages[i] è basato su 0; gli argomenti di pagina PdfFileEditor.extract()/.insert() sono basati su 1 | Aggiungi o sottrai 1 quando converti tra le due API |
IndexError: Page index out of range. da pages.delete() | L’indice passato a delete() non esiste nella collezione | Verifica doc.page_count (o len(doc.pages)) prima di eliminare |
FAQ
Devo avere una licenza per usare Aspose.PDF FOSS per Python?
No. Questa è l’edizione open-source (con licenza MIT); non esiste alcun file di licenza né passo di attivazione da configurare.
Posso esportare un Document in formati diversi dal PDF?
Non in questa versione. save() implementa solo l’output PDF — fornire un altro valore SaveFormat/DocFormat genera UnsupportedFeatureException invece di produrre un file con etichetta errata.
Qual è la differenza tra Document.merge() e il plugin Merger?
Document.merge() combina le istanze Document che hai già aperto in memoria. Merger (con MergeOptions e FileDataSource) è un wrapper di convenienza file-a-file che apre, unisce e salva per te in una sola chiamata — utile per script batch semplici che non hanno mai bisogno dell’oggetto intermedio Document.
Perché pages.insert() non solleva mai un’eccezione per un indice fuori intervallo?
PageCollection.insert() limita l’indice all’intervallo valido (i valori negativi diventano 0, i valori oltre la fine diventano len(doc.pages)) invece di sollevare un’eccezione, così un inserimento non fallisce mai solo a causa del valore dell’indice.
Come posso caricare in modo sicuro un PDF da una fonte non affidabile?
Costruisci un PdfLoadLimits con limiti espliciti (max_input_bytes, max_pages, max_objects, e così via) e passalo come argomento limits= a Document(...) o load_from(). Ogni campo ha già un valore finito di default, ma restringerli alla dimensione di input prevista riduce le risorse che un file malformato può consumare.
API Reference Riepilogo
| Classe / Metodo | Descrizione |
|---|---|
Document() / Document.load_from | Crea un documento vuoto o caricane uno da un percorso, da byte o da un flusso binario |
Document.save | Scrivi il documento su un percorso o su un flusso scrivibile (solo PDF) |
Document.dispose() / Document.close() | Rilascia le risorse del motore; idempotente |
Document.pages | Il PageCollection del documento |
Document.info | Metadati del documento come un dict[str, str] |
Document.optimize / Document.optimize_resources / Document.compress_streams() | Rimuovi le risorse inutilizzate e comprimi i flussi |
Document.merge() | Accoda altre istanze di Document a questa |
Document.encrypt / Document.decrypt / Document.change_passwords | Applica, rimuovi o ruota le password del documento |
Document.validate() / Document.check() / Document.repair() | Verifica e tenta di correggere l’integrità strutturale |
PageCollection.add() / .insert() / .delete() / .item() | Modifiche strutturali alla raccolta di pagine (basato su zero) |
Page.rect / Page.rotation / Page.index | Geometria e posizione per pagina |
OptimizationOptions | Flag di granularità fine consumati da Document.optimize |
MergeOptions / Merger | Plugin di fusione file-a-file |
SplitOptions / Splitter | Plugin di divisione file-a-file una pagina per output |
FileDataSource | Input/output basato su file per le API del plugin |
PdfFileEditor | Facade per concatenate(), extract(), insert(), delete(), append() (pagine indicizzate a partire da 1) |
PdfLoadLimits | Policy immutabile di limite delle risorse per input non attendibile |
AsposePdfException | Classe base per ogni eccezione sollevata dalla libreria |
PdfSecurityException | Sollevata per password mancanti o errate e errori di permessi |
PdfIOException | Sollevata per errori di I/O durante l’elaborazione del PDF |
Vedi anche
- API Reference: Documentazione completa della classe e dei metodi per
aspose_pdf - Base di conoscenza:Guide pratiche orientate al compito
- Panoramica del prodotto: Riepilogo delle funzionalità e capacità
- Guida introduttiva / Installazione: installazione e configurazione
- Aspose.PDF for Python — Enterprise Documentation