كيفية تحميل مستند في C++
Aspose.PDF FOSS لـ 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 عندما لا يكون الملف موجودًا أو لا يمكن قراءته، ويرمي std::runtime_error عندما لا يكون الملف PDF صالحًا:
#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() تُعيد 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
الخطوة 6: تحديث البيانات الوصفية وحفظ المستند
قم بتعيين البيانات الوصفية عبر تجاوزات الدالة 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) ذو الوسيطتين بدلاً من ذلك — فهو التحميل الزائد الوحيد الذي يملأ حالة التشفير.
المُنشئ ذو المتغيرين يرمي std::runtime_error
هذا يعني أن ملف PDF المصدر يحتوي على مدخل /Encrypt في الـtrailer وأن كلمة المرور المقدَّمة لا تطابق كلمة مرور المستخدم ولا كلمة مرور المالك المسجلة هناك. امسك std::runtime_error واطلب كلمة المرور الصحيحة، أو أكد كلمة المرور خارج القناة قبل إعادة المحاولة.
Save() يرمي “لا يوجد اسم ملف مصدر للحفظ فيه”
المُنشئ Save() بدون وسائط يكتب مرةً أخرى إلى المسار الذي تم إنشاء المستند منه. الـDocument المُنشأ باستخدام المُنشئ بدون وسائط — مستند جديد في الذاكرة دون ملف مصدر — لا يمتلك مسارًا للكتابة إليه، لذا يرمى Save(). استدعِ Save(outputFileName) بدلاً من ذلك.
Decrypt() لا يبدو أنه يُنتج ملفًا غير محمي
Decrypt() يمسح علامة IsEncrypted() في الذاكرة بحيث تُعامل القراءات اللاحقة المستند كنص عادي، لكن في الإصدار الحالي لا يعيد كتابة قاموس /Encrypt في الـtrailer ولا يعيد ترميز السلاسل والتدفقات المشفرة. استدعاء Save() بعد Decrypt() لا يزال يكتب البايتات الأصلية، بما في ذلك التشفير الأصلي — هذه الطريقة لا تنتج نسخة نصية عادية على القرص بعد.
العنوان/المؤلف/إلخ. يُطبع كسلاسل فارغة
تُعيد مُحَصِّلات DocumentInfo سلسلة فارغة، وليس خطأ، عندما يكون مفتاح /Info المقابل غير موجود في ملف PDF المصدر. النتيجة الفارغة تعني أن الحقل لم يُحدد أبداً في ذلك المستند، وليس أن القراءة فشلت.
الأسئلة المتكررة
هل يعمل Document(path) على PDF مشفر؟
عادةً ما يقوم بتحليل شجرة الصفحات دون إلقاء استثناء، لكنه لا يتحقق من كلمة المرور أبداً ويترك IsEncrypted() دائمًا عند false. استخدم المُنشئ ذو الوسيطين كلما كان من الممكن أن يكون المصدر مشفراً.
هل من الآمن تمرير كلمة مرور إلى Document(path, password) لملف يتضح لاحقًا أنه غير مشفر؟
نعم. عندما لا يحتوي التذييل على إدخال /Encrypt، يتم تجاهل معامل كلمة المرور ويُفتح المستند بالطريقة نفسها التي يُفتح بها باستخدام المُنشئ ذو الوسيط الواحد.
كيف أتمييز مفتاح /Info مخصص عن المفتاح المدمج؟
استدعِ الثابت DocumentInfo::IsPredefinedKey(key). يُعيد true لـ Title, Author, Subject, Keywords, Creator, Producer, وTrapped، وfalse لأي شيء آخر.
هل يمكنني استبدال الملف الذي قمت بتحميله للتو بدلاً من الكتابة إلى مسار جديد؟
نعم — استدعِ Save() بدون وسائط على Document الذي تم إنشاؤه من مسار ملف؛ فهو يكتب مرة أخرى إلى نفس مسار المصدر. يطرح استثناءً للوثائق التي تم بناؤها باستخدام المُنشئ بدون وسائط، والتي لا تمتلك مسار مصدر.
هل يؤدي الحفظ بعد Decrypt() إلى إزالة حماية كلمة مرور ملف PDF؟
لا، ليس في الإصدار الحالي — راجع المشكلات الشائعة أعلاه. Decrypt() يؤثر فقط على حالة الذاكرة المستخدمة من قبل قُرّاء المحتوى؛ الملف الذي يكتبه Save() لا يزال يحمل القاموس الأصلي /Encrypt.