چگونه یک سند را در C++ بارگذاری کنیم

چگونه یک سند را در C++ بارگذاری کنیم

Aspose.PDF FOSS برای C++ یک PDF موجود را از طریق کلاس Document باز می‌کند — از مسیر فایل ساده، یا با رمز عبور وقتی منبع رمزنگاری شده باشد — و متادیتای /Info فایل را از طریق DocumentInfo در دسترس می‌گذارد. این راهنما به بارگذاری سند، تشخیص و باز کردن فایل‌های محافظت‌شده با رمز عبور، خواندن و به‌روزرسانی متادیتای عنوان/نویسنده/تولیدکننده، و ذخیره نتیجه می‌پردازد. کتابخانه از طریق CMake به پروژه اضافه می‌شود؛ هیچ مرحله نصب از طریق مدیر بسته وجود ندارد.

راهنمای گام‌به‌گام

گام ۱: نصب بسته

کتابخانه را به عنوان زیرشاخه 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 را چاپ می‌کند، تأیید می‌دارد که کتابخانه به‌درستی لینک شده است.


مرحله ۲: وارد کردن کلاس‌های مورد نیاز

#include <aspose/pdf/document.hpp>
#include <aspose/pdf/document_info.hpp>

using namespace Aspose::Pdf;

Document و DocumentInfo هر دو مستقیماً تحت فضای‌نام Aspose::Pdf اعلان شده‌اند.


مرحله ۳: باز کردن سند 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";
}

مرحله ۴: باز کردن سند محافظت‌شده با رمز عبور

سازنده تک‌آرگومان از مرحله ۳ هرگز رمز عبور را تأیید نمی‌کند یا ورودی /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 منبع رمزنگاری نشده باشد، آرگومان رمز عبور صرفاً نادیده گرفته می‌شود و سند به‌صورت عادی باز می‌شود — بنابراین استفاده از سازنده دو‌آرگومان حتی زمانی که مطمئن نیستید فایلی محافظت‌شده است، ایمن است.


مرحله ۵: خواندن فراداده سند با DocumentInfo

Document.Info() یک DocumentInfo& برگردانده که به دیکشنری /Info سند متصل است. هر فیلد از پیش تعریف‌شده دسترسی‌خوانی مخصوص به خود را دارد که در صورت عدم وجود کلید در فایل منبع، یک رشته خالی برمی‌گرداند:

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

مرحله ۶: به‌روزرسانی فراداده و ذخیره سند

متادیتا را از طریق overloadهای setter متناظر، یا از طریق متد راحتی SetTitle بر روی Document تنظیم کنید، سپس تغییرات را با 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) باز کنید — این تنها overload است که وضعیت رمزگذاری را پر می‌کند.

سازندهٔ دو آرگومان استثنا می‌اندازد std::runtime_error

این به این معناست که PDF منبع یک ورودی /Encrypt در تریلر خود دارد و رمز عبوری که ارائه شده نه با رمز کاربر و نه با رمز مالک ثبت‌شده در آن مطابقت دارد. std::runtime_error را بگیرید و برای رمز صحیح درخواست کنید، یا قبل از تلاش مجدد رمز را به‌صورت خارج از باند تأیید کنید.

Save() استثنا می‌اندازد «no source filename to save to»

سازنده بدون آرگومان Save() به مسیری که سند از آن ساخته شده بازنویسی می‌کند. یک Document که با سازنده بدون آرگومان ایجاد شده — سندی جدید در حافظه که فایل منبعی ندارد — مسیری برای بازنویسی ندارد، بنابراین Save() پرتاب می‌شود. به‌جای آن Save(outputFileName) را فراخوانی کنید.

Decrypt() به‌نظر نمی‌رسد فایلی بدون محافظت تولید کند

Decrypt() پرچم IsEncrypted() در حافظه را پاک می‌کند تا خواندن‌های بعدی سند را به‌عنوان متن ساده درنظر بگیرند، اما در نسخهٔ فعلی، دیکشنری /Encrypt تریلر را بازنویسی نمی‌کند و رشته‌ها و جریان‌های رمزگذاری‌شده را دوباره رمزگذاری نمی‌کند. فراخوانی Save() پس از Decrypt() هنوز بایت‌های اصلی را بازنویسی می‌کند، از جمله رمزگذاری اولیه — این روش هنوز یک نسخهٔ متن ساده روی دیسک تولید نمی‌کند.

عنوان/نویسنده/و غیره به‌صورت رشته‌های خالی چاپ می‌شوند

دسترس‌گیرهای DocumentInfo وقتی کلید /Info متناظر در PDF منبع موجود نیست، یک رشتهٔ خالی برمی‌گردانند، نه خطا. یک نتیجهٔ خالی به این معنی است که فیلد در آن سند هرگز تنظیم نشده است، نه اینکه خواندن شکست خورده باشد.

سوالات متداول

آیا Document(path) روی یک PDF رمزگذاری‌شده کار می‌کند؟

به طور معمول درخت صفحات را بدون پرتاب استثنا تجزیه می‌کند، اما هرگز رمز عبور را احراز هویت نمی‌کند و همیشه IsEncrypted() را در false می‌گذارد. هر زمان که منبع ممکن است رمزگذاری شده باشد، سازندهٔ دو آرگومان را استفاده کنید.

آیا امن است که یک رمز عبور را به Document(path, password) برای فایلی که در واقع رمزگذاری نشده است، پاس بدهیم؟

بله. وقتی trailer هیچ ورودی /Encrypt ندارد، آرگومان رمز عبور نادیده گرفته می‌شود و سند به همان روشی که با سازندهٔ تک‌آرگومان باز می‌شد، باز می‌شود.

چگونه می‌توانم کلید سفارشی /Info را از یک کلید پیش‌فرض تشخیص دهم؟

متد استاتیک DocumentInfo::IsPredefinedKey(key) را فراخوانی کنید. برای Title، Author، Subject، Keywords، Creator، Producer و Trapped مقدار true برمی‌گرداند و برای سایر موارد مقدار false.

آیا می‌توانم فایل بارگذاری‌شده را بازنویسی کنم به جای نوشتن در مسیر جدید؟

بله — Save() بدون آرگومان را بر روی یک Document که از مسیر فایل ساخته شده است فراخوانی کنید؛ این کار به همان مسیر منبع بازمی‌نویسد. برای اسنادی که با سازنده بدون آرگومان ساخته شده‌اند و مسیر منبع ندارند، استثنا می‌اندازد.

آیا ذخیره‌سازی پس از Decrypt() حفاظت با رمز عبور PDF را حذف می‌کند؟

خیر، در نسخهٔ فعلی این‌طور نیست — به بخش مشکلات رایج در بالا مراجعه کنید. Decrypt() فقط بر وضعیت در-حافظه‌ای که توسط خوانندگان محتوا استفاده می‌شود تأثیر می‌گذارد؛ فایلی که توسط Save() نوشته می‌شود همچنان واژه‌نامهٔ اصلی /Encrypt را حمل می‌کند.

همچنین ببینید:

 فارسی