Como Carregar um Documento em C++

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.

Ver também

 Português