วิธีโหลดเอกสารใน C++

วิธีโหลดเอกสารใน 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 ดั้งเดิม.

ดูเพิ่มเติม

 ภาษาไทย