How to Work with the Facades API in Aspose.PDF FOSS for C++
Aspose.PDF FOSS for C++ groups a set of higher-level facade and editor classes —
PdfExtractor, PdfBookmarkEditor, PdfContentEditor, PdfAnnotationEditor,
FormEditor, PdfFileEditor, and PdfConverter among them — in the
Aspose::Pdf::Facades namespace. Each one wraps a single document-maintenance task on
top of the core Document API, so you can extract content, edit bookmarks, or fill
form fields without hand-rolling the underlying page and object walks yourself. This
guide focuses on PdfExtractor, the facade used to pull embedded file attachments,
page text, and embedded images out of an existing PDF.
Step-by-Step Guide
Step 1: Install the Package
Add Aspose.PDF FOSS for C++ as a CMake subdirectory and link the static library target:
git clone https://github.com/aspose-pdf-foss/Aspose.PDF-FOSS-for-Cpp.gitadd_subdirectory(Aspose.PDF-FOSS-for-Cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)Confirm the toolchain and link step resolve correctly before writing any facade code:
cmake -S . -B build
cmake --build buildA clean build against a C++20 compiler confirms aspose_pdf_foss is linked into
your_app.
Step 2: Import Required Classes
PdfExtractor lives under aspose/pdf/facades/, alongside Document from the core
namespace:
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/facades/pdf_extractor.hpp>
using namespace Aspose::Pdf;
using namespace Aspose::Pdf::Facades;Step 3: Bind a Document to PdfExtractor
Every facade class derives from a common Facade base that exposes BindPdf(srcFile)
and BindPdf(srcDoc) to attach it to a document after construction. PdfExtractor
also accepts an already-open Document directly in its constructor, which is the
pattern used throughout this guide:
Document doc("input.pdf");
PdfExtractor extractor(doc);Step 4: Extract Embedded File Attachments
Check Document::EmbeddedFiles() first, then read the attachment names with
GetAttachNames() and pull an attachment’s bytes out to disk with GetAttachment():
#include <iostream>
if (doc.EmbeddedFiles().Count() > 0) {
std::vector<std::string> names = extractor.GetAttachNames();
for (const auto& name : names) {
std::cout << "Attachment: " << name << "\n";
}
// Writes the bytes of the first attachment to disk
extractor.GetAttachment("extracted_attachment.bin");
}Step 5: Extract Text from Every Page
ExtractText() followed by GetText() writes the whole document’s text to a single
file:
extractor.ExtractText();
extractor.GetText("extracted_text.txt");To capture one file per page instead, set the page range with StartPage() /
EndPage(), then drive HasNextPageText() / GetNextPageText() in a loop, giving
each call its own output path:
extractor.StartPage(1);
extractor.EndPage(doc.Pages().Count());
int pageNumber = extractor.StartPage();
while (extractor.HasNextPageText()) {
std::string outputFile = "page_" + std::to_string(pageNumber) + ".txt";
extractor.GetNextPageText(outputFile);
++pageNumber;
}Step 6: Extract Embedded Images
ExtractImage() primes the image cursor; HasNextImage() / GetNextImage() then
walk the images one at a time, writing each to the path you pass in:
extractor.ExtractImage();
int imageIndex = 1;
while (extractor.HasNextImage()) {
std::string outputFile = "extracted_image_" + std::to_string(imageIndex);
if (extractor.GetNextImage(outputFile)) {
++imageIndex;
}
}Common Issues and Fixes
GetAttachNames() returns an empty vector. The source PDF has no embedded files.
Check doc.EmbeddedFiles().Count() before calling any attachment method on
PdfExtractor so you don’t attempt to extract from a document that never had
attachments.
The page-text loop never enters the body. HasNextPageText() returns false
immediately if StartPage() / EndPage() were never set, or if they were set to a
range outside the document’s actual page count. Set the range explicitly from
doc.Pages().Count() before checking HasNextPageText().
GetNextImage() returns false on the first call. ExtractImage() must be
called once to prime the image cursor before you check HasNextImage() or call
GetNextImage(). Calling GetNextImage() without a prior ExtractImage() call is
undefined from the caller’s perspective — always call ExtractImage() first.
Every extracted image or page-text file overwrites the previous one.
GetNextImage() and GetNextPageText() each take a literal output path; the facade
does not generate unique filenames for you. Build a distinct path per iteration (for
example, by appending an incrementing counter) as shown in Steps 5 and 6.
Link error: undefined reference to aspose_pdf_foss symbols. Confirm
add_subdirectory() points at the cloned repository root and that
target_link_libraries() names the aspose_pdf_foss target exactly, with a C++20
standard configured for your_app.
Frequently Asked Questions
What’s the difference between the Facades API and the core Document API?
The core Document API (Document, PageCollection, Annotation, and so on) exposes
the PDF object model directly. Facade classes such as PdfExtractor sit on top of it
and package a specific multi-step task — extracting content, editing bookmarks,
filling form fields — behind a narrower, purpose-built interface.
Can I edit bookmarks or fill form fields the same way I extract content with PdfExtractor?
Yes. PdfBookmarkEditor (with CreateBookmarks(), ModifyBookmarks(),
ExtractBookmarks(), and DeleteBookmarks()) and FormEditor (with AddField(),
RemoveField(), and SetFieldAttribute()) live in the same Aspose::Pdf::Facades
namespace and follow the same include/construct pattern shown in Steps 2 and 3 —
each just operates on a different part of the document.
Can PdfExtractor read a password-protected PDF?
Set the password before calling any extraction method:
extractor.Password("owner-or-user-password");PdfExtractor::Password() is a plain read/write property, so it must be set ahead of
ExtractText(), ExtractImage(), or the attachment methods.
What happens if the PDF has no text, images, or attachments to extract?
Nothing throws. GetAttachNames() returns an empty vector, and HasNextPageText() /
HasNextImage() return false on the first check, so the corresponding loop body
simply never runs.
Which header do I include for a specific facade class?
Each facade class ships its own header under aspose/pdf/facades/, matching the
class name: pdf_extractor.hpp for PdfExtractor, pdf_bookmark_editor.hpp for
PdfBookmarkEditor, form_editor.hpp for FormEditor, and bookmark.hpp for the
Bookmark / Bookmarks value types.