How to Load a Document in C++
Aspose.PDF FOSS for C++ opens an existing PDF through the Document class — from a plain file path, or with a password when the source is encrypted — and exposes the file’s /Info metadata through DocumentInfo. This guide covers loading a document, detecting and opening password-protected files, reading and updating title/author/producer metadata, and saving the result. The library is added to a project via CMake; there is no package-manager install step.
Step-by-Step Guide
Step 1: Install the Package
Add the library as a CMake subdirectory and link against the aspose_pdf_foss target:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)Verify the toolchain and headers resolve by compiling a minimal program:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}A successful build that prints pages: 0 confirms the library is linked correctly.
Step 2: Import Required Classes
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>
using namespace Aspose::Pdf;Document and DocumentInfo are both declared directly under the Aspose::Pdf namespace.
Step 3: Open a PDF Document from a File Path
The Document(filename) constructor reads the file, parses its cross-reference table and page tree, and builds the in-memory model. It throws std::system_error when the file does not exist or cannot be read, and std::runtime_error when the file is not a valid 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";
}Step 4: Open a Password-Protected Document
The single-argument constructor from Step 3 never authenticates a password or inspects the trailer’s /Encrypt entry, so IsEncrypted() on a document opened that way always reports false — even when the source file really is encrypted. To detect and open an encrypted PDF, use the two-argument constructor, which reads /Encrypt and authenticates the password you supply:
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";
}If the source PDF is not encrypted, the password argument is simply ignored and the document opens normally — so it is safe to use the two-argument constructor even when you are not certain a file is protected.
Step 5: Read Document Metadata with DocumentInfo
Document.Info() returns a DocumentInfo& bound to the document’s /Info dictionary. Each predefined field has its own read accessor, which returns an empty string when the key is absent from the source file:
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 reports whether a given /Info key name is one of these built-in fields, as opposed to a custom key added with Add:
bool builtin = DocumentInfo::IsPredefinedKey("Title"); // true
bool custom = DocumentInfo::IsPredefinedKey("MyKey"); // false
Step 6: Update Metadata and Save the Document
Set metadata through the matching setter overloads, or through the SetTitle convenience method on Document, then persist the change with Save:
Document doc("input.pdf");
doc.Info().Author("Report Generator");
doc.SetTitle("Quarterly Report"); // equivalent to doc.Info().Title(title)
doc.Save("output.pdf");Metadata edits are staged in memory and only written out on the next Save call. Call Save(outputFileName) to write to a new path, or the no-argument Save() to overwrite the file a document was originally opened from:
Document doc("input.pdf");
doc.SetTitle("Updated In Place");
doc.Save(); // writes back to "input.pdf"
Common Issues and Fixes
IsEncrypted() returns false for a PDF I know is password-protected
The single-argument Document(path) constructor never authenticates against the file’s /Encrypt dictionary, so IsEncrypted() always reports false on a document opened this way, regardless of whether the source is actually encrypted. Open the file with the two-argument Document(path, password) constructor instead — it is the only overload that populates the encryption state.
The two-argument constructor throws std::runtime_error
This means the source PDF has a /Encrypt entry in its trailer and the password supplied matched neither the user nor the owner password recorded there. Catch std::runtime_error and prompt for the correct password, or confirm the password out-of-band before retrying.
Save() throws “no source filename to save to”
The no-argument Save() writes back to the path a document was constructed from. A Document created with the no-argument constructor — a fresh, in-memory document with no source file — has no path to write back to, so Save() throws. Call Save(outputFileName) instead.
Decrypt() doesn’t seem to produce an unprotected file
Decrypt() clears the in-memory IsEncrypted() flag so downstream reads treat the document as plaintext, but in the current release it does not rewrite the trailer’s /Encrypt dictionary or re-encode encrypted strings and streams. A Save() call after Decrypt() still writes back the original bytes, including the original encryption — this method does not yet produce a plaintext copy on disk.
Title/Author/etc. print as empty strings
DocumentInfo accessors return an empty string, not an error, when the corresponding /Info key is absent from the source PDF. An empty result means the field was never set on that document, not that the read failed.
Frequently Asked Questions
Does Document(path) work on an encrypted PDF?
It typically parses the page tree without throwing, but it never authenticates a password and always leaves IsEncrypted() at false. Use the two-argument constructor whenever the source might be encrypted.
Is it safe to pass a password to Document(path, password) for a file that turns out not to be encrypted?
Yes. When the trailer has no /Encrypt entry, the password argument is ignored and the document opens the same way it would with the single-argument constructor.
How do I tell a custom /Info key from a built-in one?
Call the static DocumentInfo::IsPredefinedKey(key). It returns true for Title, Author, Subject, Keywords, Creator, Producer, and Trapped, and false for anything else.
Can I overwrite the file I just loaded instead of writing to a new path?
Yes — call the no-argument Save() on a Document that was constructed from a file path; it writes back to that same source path. It throws for documents built with the no-argument constructor, which have no source path.
Does saving after Decrypt() remove the PDF’s password protection?
No, not in the current release — see Common Issues above. Decrypt() only affects in-memory state used by content readers; the file written by Save() still carries the original /Encrypt dictionary.