C++에서 문서를 로드하는 방법
Aspose.PDF FOSS for 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을(를) 발생시키고, 파일이 유효한 PDF가 아닐 때는 std::runtime_error을(를) 발생시킵니다:
#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()은(는) 문서의 /Info 사전에 바인딩된 DocumentInfo&을 반환합니다. 각 사전 정의된 필드에는 자체 읽기 접근자가 있으며, 해당 키가 소스 파일에 없을 경우 빈 문자열을 반환합니다:
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: 메타데이터 업데이트 및 문서 저장
일치하는 setter 오버로드 또는 Document의 SetTitle 편의 메서드를 통해 메타데이터를 설정한 다음, 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 사전을 다시 쓰거나 암호화된 문자열 및 스트림을 재인코딩하지 않습니다. Decrypt() 이후에 Save()을 호출해도 원본 바이트(원래 암호화 포함)를 그대로 기록합니다 — 이 메서드는 아직 디스크에 평문 복사본을 생성하지 못합니다.
Title/Author/etc.가 빈 문자열로 출력됩니다
DocumentInfo 접근자는 해당 /Info 키가 원본 PDF에 없을 때 오류가 아니라 빈 문자열을 반환합니다. 빈 결과는 해당 문서에서 필드가 설정되지 않았음을 의미하며, 읽기가 실패한 것이 아닙니다.
자주 묻는 질문
Document(path)가 암호화된 PDF에서 작동합니까?
보통 예외를 발생시키지 않고 페이지 트리를 파싱하지만, 비밀번호를 인증하지 않으며 항상 IsEncrypted()를 false에 두고 남깁니다. 소스가 암호화될 가능성이 있을 때는 항상 두 인수 생성자를 사용하십시오.
실제로 암호화되지 않은 파일에 대해 Document(path, password)에 비밀번호를 전달하는 것이 안전합니까?
예. 트레일러에 /Encrypt 항목이 없을 경우 비밀번호 인자는 무시되며, 문서는 단일 인수 생성자를 사용할 때와 동일한 방식으로 열립니다.
사용자 정의 /Info 키와 내장 키를 어떻게 구분할 수 있나요?
정적 DocumentInfo::IsPredefinedKey(key)을 호출하십시오. Title, Author, Subject, Keywords, Creator, Producer, Trapped에 대해 true을 반환하고, 그 외의 경우에는 false을 반환합니다.
로드한 파일을 새 경로에 쓰는 대신 덮어쓸 수 있나요?
예 — 파일 경로에서 생성된 Document에 인수 없는 Save()을 호출하면 됩니다; 동일한 원본 경로에 다시 씁니다. 원본 경로가 없는 인수 없는 생성자로 만든 문서에 대해서는 예외가 발생합니다.
Decrypt() 후에 저장하면 PDF의 비밀번호 보호가 제거되나요?
아니요, 현재 릴리스에서는 지원되지 않습니다 — 위의 Common Issues를 참고하십시오. Decrypt()은 콘텐츠 리더에서 사용하는 메모리 내 상태에만 영향을 미칩니다; Save()이(가) 기록한 파일은 여전히 원본 /Encrypt 사전을 포함합니다.