Як завантажити документ у C++
Aspose.PDF FOSS для C++ відкриває існуючий PDF за допомогою класу Document — з простого шляху до файлу, або з паролем, коли джерело зашифровано — і надає доступ до /Info метаданих файлу через DocumentInfo. Цей посібник охоплює завантаження документа, виявлення та відкриття файлів, захищених паролем, читання та оновлення метаданих назви/автора/виробника, а також збереження результату. Бібліотеку додають до проєкту за допомогою CMake; кроку встановлення через менеджер пакетів немає.
Покроковий посібник
Крок 1: Встановити пакет
Додайте бібліотеку як підкаталог CMake і зв’яжіть її з ціллю aspose_pdf_foss:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)Перевірте, чи інструментарій і заголовки успішно знаходяться, скомпілювавши мінімальну програму:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}Успішна збірка, яка виводить pages: 0, підтверджує, що бібліотеку правильно зв’язано.
Крок 2: Імпорт необхідних класів
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>
using namespace Aspose::Pdf;Document і DocumentInfo оголошені безпосередньо в просторі імен Aspose::Pdf.
Крок 3: Відкрити PDF-документ за шляхом до файлу
Конструктор Document(filename) зчитує файл, аналізує його таблицю перехресних посилань та дерево сторінок, і створює модель у пам’яті. Він генерує std::system_error, якщо файл не існує або його не вдається прочитати, і std::runtime_error, якщо файл не є дійсним 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";
}Крок 4: Відкрити документ, захищений паролем
Конструктор з одним аргументом з Кроку 3 ніколи не автентифікує пароль і не перевіряє запис /Encrypt у трейлері, тому IsEncrypted() у документі, відкритому таким способом, завжди повідомляє false — навіть якщо вихідний файл дійсно зашифрований. Щоб виявити та відкрити зашифрований PDF, використайте конструктор з двома аргументами, який зчитує /Encrypt і автентифікує наданий вами пароль:
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";
}Якщо вихідний PDF не зашифрований, аргумент пароля просто ігнорується, і документ відкривається звичайно — тому безпечно використовувати конструктор з двома аргументами, навіть якщо ви не впевнені, що файл захищений.
Крок 5: Зчитати метадані документа за допомогою DocumentInfo
Document.Info() повертає DocumentInfo&, прив’язаний до словника /Info документа. Кожне попередньо визначене поле має власний accessor для читання, який повертає порожній рядок, якщо ключ відсутній у вихідному файлі:
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 повідомляє, чи є задана назва ключа /Info однією з вбудованих полів, на відміну від користувацького ключа, доданого за допомогою Add:
bool builtin = DocumentInfo::IsPredefinedKey("Title"); // true
bool custom = DocumentInfo::IsPredefinedKey("MyKey"); // false
Крок 6: Оновити метадані та зберегти документ
Встановіть метадані за допомогою відповідних перевантажень сеттера або за допомогою зручного методу SetTitle у Document, а потім збережіть зміни за допомогою Save:
Document doc("input.pdf");
doc.Info().Author("Report Generator");
doc.SetTitle("Quarterly Report"); // equivalent to doc.Info().Title(title)
doc.Save("output.pdf");Редагування метаданих підготовлюються в пам’яті і записуються лише під час наступного виклику Save. Викличте Save(outputFileName), щоб записати у новий шлях, або безаргументний Save(), щоб перезаписати файл, з якого документ спочатку був відкритий:
Document doc("input.pdf");
doc.SetTitle("Updated In Place");
doc.Save(); // writes back to "input.pdf"
Поширені проблеми та виправлення
IsEncrypted() returns false для PDF, який я знаю, захищений паролем
Конструктор Document(path) з одним аргументом ніколи не автентифікує проти словника /Encrypt файлу, тому IsEncrypted() завжди повідомляє false для документа, відкритого таким чином, незалежно від того, чи зашифровано джерело насправді. Відкрийте файл за допомогою конструктора Document(path, password) з двома аргументами — це єдиний перегружений варіант, який заповнює стан шифрування.
Конструктор з двома аргументами викидає std::runtime_error
Це означає, що у вихідного PDF у трейлері є запис /Encrypt, і вказаний пароль не збігся ні з користувацьким, ні з паролем власника, що там записані. Перехопіть std::runtime_error і запросіть правильний пароль, або підтвердіть пароль поза каналом перед повторною спробою.
Save() викидає “no source filename to save to”
Конструктор Save() без аргументів записує назад у шлях, з якого був створений документ. Document, створений за допомогою конструктора без аргументів — новий документ у пам’яті без вихідного файлу — не має шляху для запису назад, тому Save() генерує виключення. Використайте Save(outputFileName) замість цього.
Decrypt() здається, не створює незахищений файл
Decrypt() очищає у пам’яті прапорець IsEncrypted(), тому подальші читання розглядають документ як простий текст, але у поточному випуску він не переписує словник /Encrypt у трейлері і не перекодує зашифровані рядки та потоки. Виклик Save() після Decrypt() все ще записує оригінальні байти, включаючи початкове шифрування — цей метод ще не створює копію простого тексту на диску.
Title/Author/тощо. виводяться порожніми рядками
DocumentInfo аксесори повертають порожній рядок, а не помилку, коли відповідний /Info ключ відсутній у вихідному PDF. Порожній результат означає, що поле ніколи не було встановлене в цьому документі, а не те, що читання не вдалося.
Поширені запитання
Чи працює Document(path) з зашифрованим PDF?
Зазвичай вона аналізує дерево сторінок без виключень, але ніколи не автентифікує пароль і завжди залишає IsEncrypted() у false. Використовуйте конструктор з двома аргументами, коли джерело може бути зашифровано.
Чи безпечно передавати пароль у Document(path, password) для файлу, який виявився незашифрованим?
Так. Коли у трейлері відсутній запис /Encrypt, аргумент пароля ігнорується, і документ відкривається так само, як і при використанні конструктора з одним аргументом.
Як розрізнити користувацький /Info ключ від вбудованого?
Викличте статичний DocumentInfo::IsPredefinedKey(key). Він повертає true для Title, Author, Subject, Keywords, Creator, Producer і Trapped, а false — для будь-якого іншого.
Чи можу я перезаписати файл, який щойно завантажив, замість запису в новий шлях?
Так — викличте Save() без аргументів на Document, який був створений з шляху до файлу; він записує назад у той самий шлях джерела. Він генерує виключення для документів, створених за допомогою конструктора без параметрів, які не мають шляху до джерела.
Чи видаляє збереження після Decrypt() захист PDF паролем?
Ні, не в поточному випуску — дивіться Common Issues вище. Decrypt() впливає лише на стан у пам’яті, який використовується читачами вмісту; файл, записаний за допомогою Save(), все ще містить оригінальний словник /Encrypt.