Zarządzanie dokumentami
Zarządzanie dokumentami
Klasa Document jest punktem wejścia dla prawie każdej operacji w Aspose.PDF FOSS dla Python: tworzenia nowego PDF, ładowania istniejącego, edycji jego stron i zapisywania wyniku. Ten przewodnik przechodzi przez cykl życia dokumentu, operacje na kolekcji stron, optymalizację, przepływy pracy z wieloma plikami, szyfrowanie oraz wyjątki, które należy obsłużyć.
Cykl życia dokumentu: tworzenie, otwieranie i zapisywanie
Document() bez argumentów tworzy pusty dokument w pamięci. Przekaż ścieżkę do pliku, surowy bytes lub dowolny czytelny strumień binarny jako pierwszy argument (lub wywołaj load_from() explicite), aby zamiast tego załadować istniejący PDF. save() akceptuje ścieżkę lub zapisywalny strumień binarny, taki jak 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() zgłasza FileExistsError, jeśli docelowa ścieżka już istnieje, chyba że przekażesz overwrite=True. close() jest aliasem dla dispose(); oba są idempotentne, więc wywoływanie ich więcej niż raz jest bezpieczne.
Jedynie PDF jest zaimplementowany jako cel zapisu — jest to rdzeń biblioteki, w pełni działająca funkcja. Przekazanie wartości eksportu, takiej jak SaveFormat.PPTX lub DocFormat.HTML, do save() zgłasza UnsupportedFeatureException zamiast zapisać nieprawidłowo oznaczony plik, więc nieudany eksport zawsze jest wyraźny, a nie cichy.
Zarządzanie kolekcją stron
doc.pages jest PageCollection. Obsługuje len(), iterację i indeksowanie od zera (doc.pages[0]), a także add(), insert(index, page) i delete(index) do edycji strukturalnych. Każdy Page udostępnia index, rect (to MediaBox), oraz 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) dodaje pustą stronę, gdy wywołany jest bez argumentu. pages.insert() ogranicza indeks poza zakresem do najbliższej prawidłowej pozycji zamiast zgłaszać błąd.
Optymalizacja i kompresja dokumentów
Document.optimize wykonuje deduplikację obrazów/strumieni, zbieranie śmieci nieużywanych obiektów oraz kompresję strumienia w jednym wywołaniu. Przekaż instancję OptimizationOptions, aby kontrolować, które techniki zostaną uruchomione; pomiń ją, aby użyć standardowego profilu czyszczenia.
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() jest aliasem dla optimize(). Jeśli potrzebujesz tylko kompresji strumienia bez przebiegu czyszczenia strukturalnego, wywołaj bezpośrednio doc.compress_streams().
Łączenie, dzielenie i edycja plików
Dla dokumentów, które już masz otwarte, Document.merge() dodaje inne instancje Document do bieżącej:
from aspose_pdf import Document
base = Document("part1.pdf")
extra = Document("part2.pdf")
base.merge(extra)
base.save("combined.pdf", overwrite=True)Dla przepływów pracy plik-do-pliku bez otwierania własnego Document, wtyczki low-code Merger i Splitter przyjmują obiekt MergeOptions/SplitOptions zbudowany z wejść i wyjść 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 oferuje tę samą rodzinę operacji jako fasada, która zwraca True/False zamiast podnosić wyjątek, co jest wygodne w skryptach wsadowych:
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 liczony od 1 numery stron, w przeciwieństwie do PageCollectionindeksowanie od 0 — zobacz Typowe problemy poniżej.
Szyfrowanie i zabezpieczenia dokumentu
Document.encrypt(user_password, owner_password=None, permissions=-4) szyfruje dokument w pamięci; decrypt(password) i change_passwords(old, new_user, new_owner=None) odwracają lub obracają hasła. is_encrypted i permissions raportują bieżący stan.
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)Otwarcie zaszyfrowanego dokumentu bez hasła lub z niewłaściwym hasłem podnosi PdfSecurityException — przechwyć tę klasę (z aspose_pdf.exceptions) zamiast zakładać, że ładowanie zawsze się powiedzie.
Metadane, walidacja i obsługa wyjątków
Metadane dokumentu znajdują się w doc.info (zwykły dict[str, str]), a doc.version / doc.id udostępniają wersję nagłówka PDF oraz identyfikator pliku w trailerze. validate() (aliasowany jako check()) raportuje integralność strukturalną; repair() próbuje naprawić typowe problemy, takie jak brakująca lista stron lub MediaBox poza zakresem.
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 ogranicza pamięć i liczbę obiektów dla niepewnych plików; wywołaj PdfLoadLimits.unlimited(), aby wyłączyć wszystkie limity, gdy w pełni ufasz źródłu. AsposePdfException jest klasą bazową dla całej hierarchii wyjątków (w tym PdfIOException i PdfSecurityException), więc pojedynczy except AsposePdfException przechwytuje każdy błąd podniesiony przez bibliotekę.
Wskazówki i najlepsze praktyki
- Zawsze wywołuj
dispose()(lubclose()) naDocument, gdy skończysz z nim pracę, lub używaj go jako krótkotrwałej zmiennej lokalnej — silnik przechowuje zdekodowaną zawartość stron i obrazy w pamięci aż do zwolnienia. - Przekaż
overwrite=Truedosave()przy ponownym zapisywaniu ścieżki, którą już utworzyłeś w tym samym uruchomieniu; domyślnie jestFalsei podnosiFileExistsError. - Preferuj
doc.optimize()przed udostępnieniem wygenerowanego PDF — to pojedyncze wywołanie usuwa nieużywane obiekty i kompresuje strumienie, a zazwyczaj zauważalnie zmniejsza rozmiar wyjścia. - Ustaw politykę
PdfLoadLimitsexplicite za każdym razem, gdy wczytujesz pliki PDF z niepewnego źródła (przesyłki, załączniki e-mail, zeskrobywanie stron); domyślne ustawienia są hojne, ale ograniczone, nie stanowią granicy bezpieczeństwa, na której można ślepo polegać. - Przechwytuj
AsposePdfException(lub konkretną podklasę, taką jakPdfSecurityException) wokół wywołań ładowania/zapisu zamiast samegoException— jest to wspólna podstawa dla każdego błędu zgłaszanego przez bibliotekę.
Typowe problemy
| Problem | Przyczyna | Rozwiązanie |
|---|---|---|
FileExistsError na save() | Ścieżka docelowa już istnieje i overwrite został pozostawiony w domyślnym False | Przekaż save(path, overwrite=True) |
UnsupportedFeatureException na save() | Żądano nie-PDF save_format (np. SaveFormat.PPTX, DocFormat.HTML) | Zapisz jako PDF — każda inna wartość SaveFormat/DocFormat powoduje podniesienie UnsupportedFeatureException zamiast zapisu wyjścia |
PdfSecurityException: Password required for encrypted document | Otworzono zaszyfrowany PDF bez argumentu password | Przekaż Document(path, password="...") lub wywołaj load_from(path, password="...") |
Błąd o jeden w numerach stron pomiędzy PageCollection a PdfFileEditor | doc.pages[i] jest indeksowane od 0; argumenty stron PdfFileEditor.extract()/.insert() są indeksowane od 1 | Dodaj lub odejmij 1 przy konwertowaniu pomiędzy dwoma API |
IndexError: Page index out of range. z pages.delete() | Indeks przekazany do delete() nie istnieje w kolekcji | Sprawdź doc.page_count (lub len(doc.pages)) przed usunięciem |
FAQ
Czy potrzebuję licencji, aby używać Aspose.PDF FOSS do Python?
Nie. To jest edycja open-source (na licencji MIT); nie ma pliku licencji ani kroku aktywacji do skonfigurowania.
Czy mogę wyeksportować Document do formatów innych niż PDF?
Nie w tej wersji. save() obsługuje jedynie wyjście PDF — podanie innej wartości SaveFormat/DocFormat powoduje wyrzucenie UnsupportedFeatureException zamiast utworzenia nieprawidłowo oznaczonego pliku.
Jaka jest różnica między Document.merge() a wtyczką Merger?
Document.merge() łączy instancje Document, które już masz otwarte w pamięci. Merger (z MergeOptions i FileDataSource) jest wygodnym wrapperem file-to-file, który otwiera, scala i zapisuje za Ciebie w jednym wywołaniu — przydatnym w prostych skryptach wsadowych, które nigdy nie potrzebują pośredniego obiektu Document.
Dlaczego pages.insert() nigdy nie zgłasza błędu przy indeksie poza zakresem?
PageCollection.insert() ogranicza indeks do prawidłowego zakresu (wartości ujemne stają się 0, wartości poza końcem stają się len(doc.pages)) zamiast podnosić błąd, więc wstawienie nigdy nie kończy się niepowodzeniem wyłącznie z powodu wartości indeksu.
Jak bezpiecznie załadować plik PDF z niewiarygodnego źródła?
Utwórz PdfLoadLimits z wyraźnymi limitami (max_input_bytes, max_pages, max_objects i tak dalej) i przekaż go jako argument limits= do Document(...) lub load_from(). Każde pole ma już domyślną skończoną wartość, ale ściślejsze określenie ich do oczekiwanego rozmiaru wejścia zmniejsza zasoby, które może zużyć nieprawidłowy plik.
API Reference Podsumowanie
| Klasa / Metoda | Opis |
|---|---|
Document() / Document.load_from | Utwórz pusty dokument lub wczytaj go z ścieżki, bajtów lub strumienia binarnego |
Document.save | Zapisz dokument do ścieżki lub zapisywalnego strumienia (tylko PDF) |
Document.dispose() / Document.close() | Zwolnij zasoby silnika; idempotentny |
Document.pages | PageCollection dokumentu |
Document.info | Metadane dokumentu jako dict[str, str] |
Document.optimize / Document.optimize_resources / Document.compress_streams() | Usuń nieużywane zasoby i skompresuj strumienie |
Document.merge() | Dołącz inne wystąpienia Document do tego |
Document.encrypt / Document.decrypt / Document.change_passwords | Zastosuj, usuń lub zmień hasła dokumentu |
Document.validate() / Document.check() / Document.repair() | Sprawdź i spróbuj naprawić integralność strukturalną |
PageCollection.add() / .insert() / .delete() / .item() | Edycje strukturalne kolekcji stron (indeksowane od zera) |
Page.rect / Page.rotation / Page.index | Geometria i pozycja dla każdej strony |
OptimizationOptions | Szczegółowe flagi używane przez Document.optimize |
MergeOptions / Merger | Wtyczka łączenia plików |
SplitOptions / Splitter | Wtyczka rozdzielająca plik na plik, jedna strona na wyjście |
FileDataSource | Wejście/wyjście oparte na plikach dla API wtyczek |
PdfFileEditor | Fasada dla concatenate(), extract(), insert(), delete(), append() (strony numerowane od 1) |
PdfLoadLimits | Niezmienna polityka limitów zasobów dla niezaufanego wejścia |
AsposePdfException | Klasa bazowa dla wszystkich wyjątków podnoszonych przez bibliotekę |
PdfSecurityException | Podnoszone w przypadku brakujących/nieprawidłowych haseł i błędów uprawnień |
PdfIOException | Podnoszone w przypadku błędów I/O podczas przetwarzania PDF |
Zobacz także
- API Reference: Pełna dokumentacja klasy i metod dla
aspose_pdf - Baza wiedzy: Przewodniki praktyczne ukierunkowane na zadania
- Przegląd produktu: Podsumowanie funkcji i możliwości
- Rozpoczęcie / Instalacja: instalacja i konfiguracja
- Aspose.PDF for Python — Enterprise Documentation