Jak załadować dokument w C++

Jak załadować dokument w C++

Aspose.PDF FOSS dla C++ otwiera istniejący PDF za pomocą klasy Document — z prostą ścieżką pliku lub przy użyciu hasła, gdy źródło jest zaszyfrowane — i udostępnia metadane /Info pliku poprzez DocumentInfo. Ten przewodnik obejmuje ładowanie dokumentu, wykrywanie i otwieranie plików chronionych hasłem, odczytywanie i aktualizowanie metadanych tytułu, autora i producenta oraz zapisywanie wyniku. Biblioteka jest dodawana do projektu poprzez CMake; nie ma kroku instalacji za pomocą menedżera pakietów.

Przewodnik krok po kroku

Krok 1: Zainstaluj pakiet

Dodaj bibliotekę jako podkatalog CMake i połącz się z celem aspose_pdf_foss:

add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)

Zweryfikuj, że toolchain i nagłówki są dostępne, kompilując minimalny program:

#include <aspose/pdf/document.hpp>
#include <iostream>

int main() {
    Aspose::Pdf::Document doc;
    std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}

Pomyślna kompilacja, która wypisuje pages: 0, potwierdza, że biblioteka jest poprawnie połączona.


Krok 2: Importuj wymagane klasy

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>

using namespace Aspose::Pdf;

Document i DocumentInfo są zadeklarowane bezpośrednio w przestrzeni nazw Aspose::Pdf.


Krok 3: Otwórz dokument PDF z ścieżki pliku

Konstruktor Document(filename) odczytuje plik, analizuje jego tabelę odwołań krzyżowych i drzewo stron oraz buduje model w pamięci. Rzuca std::system_error, gdy plik nie istnieje lub nie może zostać odczytany, oraz std::runtime_error, gdy plik nie jest prawidłowym PDF:

#include <iostream>
#include <stdexcept>

try {
    Document doc("input.pdf");
    std::cout << "Pages: " << doc.Pages().Count() << "\n";
} catch (const std::runtime_error& e) {
    std::cerr << "Not a valid PDF: " << e.what() << "\n";
} catch (const std::system_error& e) {
    std::cerr << "Could not read file: " << e.what() << "\n";
}

Krok 4: Otwórz dokument zabezpieczony hasłem

Konstruktor z jednym argumentem z Kroku 3 nigdy nie uwierzytelnia hasła ani nie sprawdza wpisu /Encrypt w trailerze, więc IsEncrypted() w dokumencie otwartym w ten sposób zawsze zgłasza false — nawet gdy plik źródłowy faktycznie jest zaszyfrowany. Aby wykryć i otworzyć zaszyfrowany PDF, użyj konstruktora z dwoma argumentami, który odczytuje /Encrypt i uwierzytelnia podane przez Ciebie hasło:

try {
    Document doc("input.pdf", "user-password");
    if (doc.IsEncrypted()) {
        std::cout << "Opened an encrypted document.\n";
    }
} catch (const std::runtime_error& e) {
    // Thrown when /Encrypt is present and the password matches
    // neither the user nor the owner entry in the trailer.
    std::cerr << "Wrong password or unreadable /Encrypt dictionary: "
              << e.what() << "\n";
}

Jeśli źródłowy PDF nie jest zaszyfrowany, argument hasła jest po prostu ignorowany i dokument otwiera się normalnie — dlatego bezpiecznie jest używać konstruktora z dwoma argumentami, nawet gdy nie masz pewności, czy plik jest chroniony.


Krok 5: Odczytaj metadane dokumentu przy użyciu DocumentInfo

Document.Info() zwraca DocumentInfo& powiązany ze słownikiem /Info dokumentu. Każde predefiniowane pole ma własny dostęp odczytowy, który zwraca pusty ciąg, gdy klucz nie występuje w pliku źródłowym:

Document doc("input.pdf");
DocumentInfo& info = doc.Info();

std::cout << "Title: "    << info.Title()    << "\n";
std::cout << "Author: "   << info.Author()   << "\n";
std::cout << "Subject: "  << info.Subject()  << "\n";
std::cout << "Producer: " << info.Producer() << "\n";
std::cout << "Creator: "  << info.Creator()  << "\n";
std::cout << "Keywords: " << info.Keywords() << "\n";

DocumentInfo::IsPredefinedKey informuje, czy podana nazwa klucza /Info jest jednym z tych wbudowanych pól, w przeciwieństwie do klucza niestandardowego dodanego przy pomocy Add:

bool builtin = DocumentInfo::IsPredefinedKey("Title");   // true
bool custom  = DocumentInfo::IsPredefinedKey("MyKey");   // false

Krok 6: Zaktualizuj metadane i zapisz dokument

Ustaw metadane za pomocą odpowiednich przeciążeń setterów lub przy użyciu wygodnej metody SetTitle na Document, a następnie zachowaj zmianę przy pomocy Save:

Document doc("input.pdf");
doc.Info().Author("Report Generator");
doc.SetTitle("Quarterly Report");   // equivalent to doc.Info().Title(title)

doc.Save("output.pdf");

Edycje metadanych są przygotowywane w pamięci i zapisywane dopiero przy następnym wywołaniu Save. Wywołaj Save(outputFileName), aby zapisać do nowej ścieżki, lub bezargumentowy Save(), aby nadpisać plik, z którego dokument został pierwotnie otwarty:

Document doc("input.pdf");
doc.SetTitle("Updated In Place");
doc.Save();   // writes back to "input.pdf"

Typowe problemy i rozwiązania

IsEncrypted() returns false dla pliku PDF, o którym wiem, że jest zabezpieczony hasłem

Konstruktor Document(path) przyjmujący pojedynczy argument nigdy nie uwierzytelnia się w słowniku /Encrypt pliku, więc IsEncrypted() zawsze zgłasza false dla dokumentu otwartego w ten sposób, niezależnie od tego, czy źródło jest faktycznie zaszyfrowane. Otwórz plik przy użyciu dwuwargowego konstruktora Document(path, password) — jest to jedyny przeciążony konstruktor, który wypełnia stan szyfrowania.

Konstruktor z dwoma argumentami rzuca std::runtime_error

Oznacza to, że źródłowy PDF ma wpis /Encrypt w swoim trailerze i podane hasło nie pasuje ani do hasła użytkownika, ani do hasła właściciela tam zapisanych. Przechwyć std::runtime_error i poproś o poprawne hasło, albo potwierdź hasło poza kanałem przed ponowną próbą.

Save() rzuca “no source filename to save to”

Konstruktor Save() bez argumentów zapisuje z powrotem do ścieżki, z której dokument został utworzony. Document utworzony przy użyciu konstruktora bezargumentowego — świeży, pamięciowy dokument bez pliku źródłowego — nie ma ścieżki do zapisu, więc Save() zgłasza wyjątek. Wywołaj zamiast tego Save(outputFileName).

Decrypt() nie wydaje się tworzyć niezabezpieczonego pliku

Decrypt() usuwa flagę IsEncrypted() w pamięci, dzięki czemu dalsze odczyty traktują dokument jako zwykły tekst, ale w bieżącej wersji nie przepisuje słownika /Encrypt w trailerze ani nie rekonwertuje zaszyfrowanych łańcuchów i strumieni. Wywołanie Save() po Decrypt() wciąż zapisuje oryginalne bajty, włącznie z pierwotnym szyfrowaniem — ta metoda nie tworzy jeszcze kopii w postaci zwykłego tekstu na dysku.

Title/Author/etc. wyświetlają się jako puste ciągi

Akcesory DocumentInfo zwracają pusty ciąg znaków, a nie błąd, gdy odpowiadający klucz /Info jest nieobecny w źródłowym PDF. Pusty wynik oznacza, że pole nigdy nie zostało ustawione w tym dokumencie, a nie że odczyt się nie powiódł.

Najczęściej zadawane pytania

Czy Document(path) działa na zaszyfrowanym PDF?

Zazwyczaj parsuje drzewo stron bez wyrzucania wyjątków, ale nigdy nie uwierzytelnia hasła i zawsze pozostawia IsEncrypted() na false. Używaj konstruktora z dwoma argumentami, gdy istnieje możliwość, że źródło jest zaszyfrowane.

Czy bezpieczne jest przekazanie hasła do Document(path, password) dla pliku, który okazał się niezaszyfrowany?

Tak. Gdy w trailerze nie ma wpisu /Encrypt, argument hasła jest ignorowany i dokument otwiera się tak samo, jak przy użyciu konstruktora z jednym argumentem.

Jak odróżnić niestandardowy klucz /Info od wbudowanego?

Wywołaj statyczny DocumentInfo::IsPredefinedKey(key). Zwraca true dla Title, Author, Subject, Keywords, Creator, Producer i Trapped, oraz false dla wszystkiego innego.

Czy mogę nadpisać plik, który właśnie załadowałem, zamiast zapisywać go w nowej ścieżce?

Tak — wywołaj metodę bezargumentową Save() na Document, który został skonstruowany z ścieżki pliku; zapisuje ponownie do tej samej ścieżki źródłowej. Rzuca wyjątek dla dokumentów utworzonych przy użyciu konstruktora bezargumentowego, które nie mają ścieżki źródłowej.

Czy zapis po Decrypt() usuwa ochronę hasłem pliku PDF?

Nie, nie w tej wersji — zobacz sekcję Common Issues powyżej. Decrypt() wpływa tylko na stan w pamięci używany przez czytniki zawartości; plik zapisany przez Save() nadal zawiera oryginalny słownik /Encrypt.

Zobacz także

 Polski