วิธีโหลดเอกสารใน C++
Aspose.PDF FOSS สำหรับ C++ เปิดไฟล์ PDF ที่มีอยู่ผ่านคลาส Document — จากเส้นทางไฟล์ธรรมดา หรือด้วยรหัสผ่านเมื่อแหล่งที่มาถูกเข้ารหัส — และเปิดเผยเมตาดาต้า /Info ของไฟล์ผ่าน DocumentInfo. คู่มือนี้ครอบคลุมการโหลดเอกสาร, การตรวจจับและการเปิดไฟล์ที่ป้องกันด้วยรหัสผ่าน, การอ่านและอัปเดตเมตาดาต้า title/author/producer, และการบันทึกผลลัพธ์. ไลบรารีจะถูกเพิ่มในโปรเจกต์ผ่าน CMake; ไม่มีขั้นตอนการติดตั้งผ่านตัวจัดการแพคเกจ.
คู่มือแบบทีละขั้นตอน
ขั้นตอนที่ 1: ติดตั้งแพคเกจ
เพิ่มไลบรารีเป็นซับไดเรกทอรีของ CMake และลิงก์กับเป้าหมาย aspose_pdf_foss:
add_subdirectory(aspose.pdf-foss-for-cpp)
target_link_libraries(your_app PRIVATE aspose_pdf_foss)ตรวจสอบว่า toolchain และ header resolve โดยการคอมไพล์โปรแกรมขั้นต่ำ:
#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: อัปเดต Metadata และบันทึกเอกสาร
ตั้งค่า metadata ผ่านการ 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");การแก้ไข metadata จะถูกจัดสแตจในหน่วยความจำและจะถูกเขียนออกเพียงเมื่อมีการเรียก 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) ที่รับสองอากิวเมนต์แทน — นี่เป็นโอเวอร์โหลดเดียวที่กำหนดสถานะการเข้ารหัส.
คอนสตรัคเตอร์ที่รับอากิวเมนต์สองตัวจะ throws std::runtime_error
นี้หมายความว่า PDF ต้นทางมีรายการ /Encrypt ในเทรลเลอร์และรหัสผ่านที่ให้มาจะไม่ตรงกับรหัสผ่านผู้ใช้หรือรหัสผ่านเจ้าของที่บันทึกไว้ที่นั่น ให้จับ std::runtime_error แล้วแสดงคำขอรหัสผ่านที่ถูกต้อง หรือยืนยันรหัสผ่านผ่านช่องทางอื่นก่อนลองใหม่.
Save() throws “ไม่มีชื่อไฟล์ต้นทางสำหรับบันทึก”
คอนสตรัคเตอร์ Save() ที่ไม่มีอากิวเมนต์จะเขียนกลับไปยังพาธที่เอกสารถูกสร้างจากนั้น Document ที่สร้างด้วยคอนสตรัคเตอร์ที่ไม่มีอากิวเมนต์ — เอกสารในหน่วยความจำใหม่ที่ไม่มีไฟล์ต้นทาง — จะไม่มีพาธให้เขียนกลับ ดังนั้น Save() จะโยนข้อผิดพลาด ให้เรียก Save(outputFileName) แทน.
Decrypt() ดูเหมือนว่าจะไม่สร้างไฟล์ที่ไม่มีการป้องกัน
Decrypt() ล้างแฟล็ก IsEncrypted() ในหน่วยความจำเพื่อให้การอ่านต่อไปหลังจากนั้นถือว่าเอกสารเป็นข้อความธรรมดา แต่ในรุ่นปัจจุบันมันไม่ได้เขียนทับพจนานุกรม /Encrypt ของเทรลเลอร์หรือเข้ารหัสใหม่ของสตริงและสตรีมที่ถูกเข้ารหัส การเรียก Save() หลังจาก Decrypt() ยังคงเขียนกลับไบต์เดิมรวมถึงการเข้ารหัสเดิม — วิธีนี้ยังไม่สร้างสำเนาเป็นข้อความธรรมดาในดิสก์.
Title/Author/etc. แสดงเป็นสตริงว่าง
ตัวเข้าถึง 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 หรือไม่?
ไม่, ไม่ใช่ในเวอร์ชันปัจจุบัน — ดูส่วน Common Issues ด้านบน. Decrypt() มีผลเฉพาะต่อสถานะในหน่วยความจำที่ใช้โดยตัวอ่านเนื้อหา; ไฟล์ที่เขียนโดย Save() ยังถือพจนานุกรม /Encrypt ดั้งเดิม.