Διαχείριση Εγγράφων

Διαχείριση Εγγράφων

Διαχείριση Εγγράφων

Η κλάση 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(), επανάληψη και αρίθμηση με βάση το 0 (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 και το αναγνωριστικό αρχείου του trailer. Το 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 κάθε φορά που φορτώνετε PDFs από μη αξιόπιστη πηγή (μεταφορτώσεις, συνημμένα email, web scrapes); οι προεπιλογές είναι γενναιόδωρες αλλά πεπερασμένες, δεν αποτελούν όριο ασφαλείας στο οποίο θα πρέπει να βασίζεστε τυφλά.
  • Αντιμετωπίστε το 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="...")
Αριθμοί σελίδων off-by-one μεταξύ PageCollection και PdfFileEditordoc.pages[i] είναι 0-βάση· τα επιχειρήματα σελίδας 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) είναι ένας wrapper ευκολίας αρχείου-σε-αρχείο που ανοίγει, συγχωνεύει και αποθηκεύει για εσάς σε μία κλήση — χρήσιμο για απλά batch scripts που δεν χρειάζονται ποτέ το ενδιάμεσο αντικείμενο 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Δημιουργήστε ένα κενό έγγραφο ή φορτώστε ένα από μια διαδρομή, bytes ή δυαδική ροή
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()Δομικές επεξεργασίες συλλογής σελίδων (με βάση το 0)
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Εγείρεται για σφάλματα I/O κατά την επεξεργασία PDF

Δείτε επίσης

 Ελληνικά