Como Carregar um Documento em C++
Aspose.PDF FOSS for C++ abre um PDF existente através da classe Document — a partir de um caminho de arquivo simples, ou com uma senha quando a fonte está criptografada — e expõe os metadados /Info do arquivo via DocumentInfo. Este guia cobre o carregamento de um documento, a detecção e abertura de arquivos protegidos por senha, a leitura e atualização dos metadados title/author/producer, e a gravação do resultado. A biblioteca é adicionada a um projeto via CMake; não há etapa de instalação por gerenciador de pacotes.
Guia Passo a Passo
Etapa 1: Instalar o Pacote
Adicione a biblioteca como um subdiretório CMake e vincule ao alvo aspose_pdf_foss:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)Verifique se a cadeia de ferramentas e os cabeçalhos são resolvidos compilando um programa mínimo:
#include <aspose/pdf/document.hpp>
#include <iostream>
int main() {
Aspose::Pdf::Document doc;
std::cout << "Linked OK — pages: " << doc.Pages().Count() << "\n";
}Uma compilação bem-sucedida que imprime pages: 0 confirma que a biblioteca está vinculada corretamente.
Etapa 2: Importar Classes Necessárias
#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>
using namespace Aspose::Pdf;Document e DocumentInfo são ambos declarados diretamente sob o namespace Aspose::Pdf.
Etapa 3: Abrir um Documento PDF a partir de um Caminho de Arquivo
O construtor Document(filename) lê o arquivo, analisa sua tabela de referência cruzada e a árvore de páginas, e constrói o modelo em memória. Ele lança std::system_error quando o arquivo não existe ou não pode ser lido, e std::runtime_error quando o arquivo não é um PDF válido:
#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";
}Etapa 4: Abrir um Documento Protegido por Senha
O construtor de um único argumento da Etapa 3 nunca autentica uma senha nem inspeciona a entrada /Encrypt do trailer, portanto IsEncrypted() em um documento aberto dessa forma sempre relata false — mesmo quando o arquivo de origem realmente está criptografado. Para detectar e abrir um PDF criptografado, use o construtor de dois argumentos, que lê /Encrypt e autentica a senha fornecida:
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";
}Se o PDF de origem não estiver criptografado, o argumento de senha é simplesmente ignorado e o documento é aberto normalmente — portanto é seguro usar o construtor de dois argumentos mesmo quando você não tem certeza se o arquivo está protegido.
Etapa 5: Ler Metadados do Documento com DocumentInfo
Document.Info() devolve um DocumentInfo& vinculado ao dicionário /Info do documento. Cada campo predefinido tem seu próprio acessor de leitura, que devolve uma string vazia quando a chave está ausente no arquivo fonte:
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 informa se um determinado nome de chave /Info é um desses campos incorporados, em vez de uma chave personalizada adicionada com Add:
bool builtin = DocumentInfo::IsPredefinedKey("Title"); // true
bool custom = DocumentInfo::IsPredefinedKey("MyKey"); // false
Etapa 6: Atualizar Metadados e Salvar o Documento
Defina os metadados usando as sobrecargas de setter correspondentes, ou através do método de conveniência SetTitle em Document, e então persista a alteração com Save:
Document doc("input.pdf");
doc.Info().Author("Report Generator");
doc.SetTitle("Quarterly Report"); // equivalent to doc.Info().Title(title)
doc.Save("output.pdf");As edições de metadados são preparadas na memória e só são gravadas na próxima chamada de Save. Chame Save(outputFileName) para gravar em um novo caminho, ou o Save() sem argumentos para sobrescrever o arquivo a partir do qual o documento foi originalmente aberto:
Document doc("input.pdf");
doc.SetTitle("Updated In Place");
doc.Save(); // writes back to "input.pdf"
Problemas Comuns e Soluções
IsEncrypted() returns false para um PDF que eu sei que está protegido por senha
O construtor Document(path) de argumento único nunca autentica contra o dicionário /Encrypt do arquivo, portanto IsEncrypted() sempre relata false em um documento aberto dessa forma, independentemente de a fonte estar realmente criptografada. Abra o arquivo com o construtor Document(path, password) de dois argumentos — ele é a única sobrecarga que popula o estado de criptografia.
O construtor de dois argumentos lança std::runtime_error
Isso significa que o PDF de origem tem uma entrada /Encrypt em seu trailer e a senha fornecida não corresponde nem à senha de usuário nem à senha de proprietário registrada lá. Capture std::runtime_error e solicite a senha correta, ou confirme a senha por outro meio antes de tentar novamente.
Save() lança “no source filename to save to”
O Save() sem argumentos grava de volta no caminho a partir do qual o documento foi construído. Um Document criado com o construtor sem argumentos — um documento novo, em memória, sem arquivo de origem — não tem caminho para gravar de volta, portanto Save() lança. Chame Save(outputFileName) em vez disso.
Decrypt() não parece gerar um arquivo não protegido
Decrypt() limpa a bandeira IsEncrypted() em memória para que leituras subsequentes tratem o documento como texto simples, mas na versão atual ele não reescreve o dicionário /Encrypt do trailer nem re-encode strings and streams. Uma chamada Save() após Decrypt() ainda grava os bytes originais, incluindo a criptografia original — este método ainda não produz uma cópia em texto simples no disco.
Title/Author/etc. são impressos como strings vazias
Os acessadores de DocumentInfo retornam uma string vazia, não um erro, quando a chave /Info correspondente está ausente do PDF de origem. Um resultado vazio significa que o campo nunca foi definido naquele documento, não que a leitura falhou.
Perguntas Frequentes
O Document(path) funciona em um PDF criptografado?
Normalmente ele analisa a árvore de páginas sem lançar exceções, mas nunca autentica uma senha e sempre deixa IsEncrypted() em false. Use o construtor de dois argumentos sempre que a origem puder estar criptografada.
É seguro passar uma senha para Document(path, password) em um arquivo que acaba não estando criptografado?
Sim. Quando o trailer não tem uma entrada /Encrypt, o argumento de senha é ignorado e o documento é aberto da mesma forma que seria com o construtor de um único argumento.
Como diferenciar uma chave /Info personalizada de uma incorporada?
Chame o estático DocumentInfo::IsPredefinedKey(key). Ele retorna true para Title, Author, Subject, Keywords, Creator, Producer e Trapped, e false para qualquer outro caso.
Posso sobrescrever o arquivo que acabei de carregar em vez de gravar em um novo caminho?
Sim — chame o Save() sem argumentos em um Document que foi construído a partir de um caminho de arquivo; ele grava de volta no mesmo caminho de origem. Ele lança uma exceção para documentos criados com o construtor sem argumentos, que não têm caminho de origem.
Salvar após Decrypt() remove a proteção por senha do PDF?
Não, não na versão atual — veja Problemas Comuns acima. Decrypt() afeta apenas o estado em memória usado pelos leitores de conteúdo; o arquivo gravado por Save() ainda contém o dicionário /Encrypt original.