ตัวอย่างทำงานเต็มที่พร้อมใช้งานบน GitHub:
read-and-write-xmp-in-psd-ai-files-java

วิธีเดิมทำให้เจ็บปวด

ลองนึกภาพการทำความสะอาดคลังข้อมูลที่ไม่มีใครอยากทำ — โฟลเดอร์ที่มีไฟล์ PSD มาสเตอร์และไฟล์ AI ต้นฉบับต้องการประกาศสิทธิ์และคำสำคัญก่อนจะเข้าสู่ DAM ขั้นตอนคือ: เปิดไฟล์ใน Photoshop, เปิด File Info, พิมพ์ลิขสิทธิ์, พิมพ์คำสำคัญ, บันทึก, ปิด, ไปไฟล์ต่อไป ทุกครั้งที่บันทึกจะทำการเรนเดอร์ไฟล์แบบหลายชั้นใหม่เพียงเพื่อเปลี่ยนสตริงของเมตาดาต้า XMP สุดท้ายคลังที่สอนบทเรียนนี้ให้ฉันคือโฟลเดอร์ไฟล์ Illustrator ที่ไม่มีแท็กใครก็ค้นหาไม่ได้; เราแก้ด้วยลูป ไม่ใช่ด้วยความอดทนเพิ่ม

คูณขั้นตอนนี้ด้วยจำนวนไฟล์ในคลังแล้วมันไม่ใช่งานเล็ก ๆ อีกต่อไป แต่กลายเป็นโครงการที่ใหญ่กว่า แย่กว่านั้นคือไม่สามารถตรวจสอบได้ — ไม่มีใครสามารถพิสูจน์ได้ภายหลังว่าไฟล์ใดบ้างที่ทำเสร็จแล้ว และไฟล์ที่ถูกข้ามดูเหมือนกันจนกว่าจะมีคำถามเรื่องลิขสิทธิ์เข้ามา แพเนลยังคบเคียงการป้อนข้อมูลกับเครื่องมือออกแบบอย่างเงียบ ๆ ผู้ที่ต้องแก้เมตาดาต้าต้องมีที่นั่ง Adobe, เวิร์กสเตชันที่เปิดไฟล์มาสเตอร์หลายชั้นได้อย่างสบาย, และความอดทนรอการบันทึกที่ทำการเรนเดอร์งานศิลป์ใหม่เพียงเพื่อเปลี่ยนสตริง

ต้นทุนจริงของการทำด้วยตนเอง: เมตาดาต้าที่แก้ด้วยมือเป็นเมตาดาต้าที่ไม่มีใครสามารถตรวจสอบได้ภายหลัง; กระบวนการทิ้งร่องรอยไว้แค่ดีไซเนอร์ที่เหนื่อยล้า

มีวิธีที่ดีกว่า

GroupDocs.Metadata สำหรับ Java อ่านและเขียนแพ็กเกจ XMP โดยตรง การแคสต์ getRootPackage() ไปเป็น IXmp ทำให้แพ็กเกจ, สคีม, และอาเรย์เป็นอ็อบเจ็กต์ Java ธรรมดาเดียวกันสำหรับคอนเทนเนอร์ PSD และ AI โดยไม่ต้องใช้ซอฟต์แวร์ Adobe ใด ๆ เอกสารdocumentationระบุว่ามีรูปแบบกว่า 170+ รูปแบบที่ใช้ API เดียวกัน

ก่อนเริ่มคุณจะต้องมี:

  • JDK 8 หรือใหม่กว่า พร้อม Maven
  • GroupDocs.Metadata for Java 24.7 (get a temporary license)
  • ไฟล์ PSD หรือ AI เพื่อฝึกฝน

เพิ่ม dependency และรีโพซิทอรีของ GroupDocs ไปยัง pom.xml ของคุณ:

mvn dependency:get -Dartifact=com.groupdocs:groupdocs-metadata:24.7

companion repository มี pom.xml พร้อมตัวอย่างไฟล์ทั้งสองรูปแบบและตรวจสอบทุกขั้นตอนด้านล่าง

วิธีใหม่: สี่การดำเนินการใน Java

ขั้นตอนที่ 1 — ดูว่าไฟล์มีอะไรบรรจุอยู่

Snapshot จะดัมพ์แพ็กเกจและทุกสคีมลงใน LinkedHashMap ตัวเดียว โดยคงลำดับที่ไฟล์ประกาศไว้

// Snapshot the packet, then sweep for anything the schemes missed
Map<String, String> result = new LinkedHashMap<>();
try (Metadata metadata = new Metadata(adobeFilePath)) {
    IXmp root = (IXmp) metadata.getRootPackage();
    if (root != null && root.getXmpPackage() != null) {
        for (MetadataProperty p : root.getXmpPackage()) {
            put(result, p);
        }
        XmpSchemes schemes = root.getXmpPackage().getSchemes();
        collect(result, schemes.getDublinCore());
        collect(result, schemes.getPhotoshop());
        collect(result, schemes.getXmpBasic());
        collect(result, schemes.getCameraRaw());
    }
    for (MetadataProperty p : metadata.findProperties(new NamedPropertySpec())) {
        if (!result.containsKey(p.getName())) put(result, p);
    }
}
return result;

ตัวช่วย put และ collect เล็ก ๆ จะใช้ getInterpretedValue() เพื่อให้วันที่อ่านได้ง่าย และการสแกนตาม Specification จะจับแพ็กเกจของผู้ขาย เวอร์ชันในรีโพซิทอรีเดินผ่านสคีมเจ็ดสคีม; โครงสร้างยังคงเหมือนเดิม

ขั้นตอนที่ 2 — อ่านฟิลด์ที่ตอบคำถาม

การตรวจสอบลิขสิทธิ์ต้องการ dc:rights การค้นหาต้องการ dc:subject ทั้งสองอยู่ใน Dublin Core และการอ่านแบบสโคปนี้ใช้เพียง 9 ฟิลด์ ไม่ต้องเดินต้นไม้

// dc:* only - the interoperability fields DAM systems agree on
XmpDublinCorePackage dc = root.getXmpPackage().getSchemes().getDublinCore();
if (dc == null) return result;
for (MetadataProperty p : dc) {
    String value = "";
    if (p.getInterpretedValue() != null
            && p.getInterpretedValue().getRawValue() != null) {
        value = String.valueOf(p.getInterpretedValue().getRawValue());
    } else if (p.getValue() != null && p.getValue().getRawValue() != null) {
        value = String.valueOf(p.getValue().getRawValue());
    }
    result.put(p.getName(), value);
}

สคีม Photoshop ทำงานเช่นเดียวกันผ่าน getter ที่มีประเภท (getCity(), getCredit(), getColorMode() และอีกห้า) ครอบคลุมฟิลด์เมตาดาต้า PSD ที่ Bridge และ Lightroom อ่าน ในรีโพซิทอรีตัวอ่านจะห่อทุก getter ด้วยตัวช่วย null‑safe ทำให้ไฟล์ที่ข้อมูลน้อยคืนค่าเป็นสตริงว่างแทนการเกิดข้อผิดพลาด รายละเอียดนี้สำคัญกว่าที่ดู: จุดประสงค์ของการทำอัตโนมัติในคลังคือให้ไฟล์แปลก ๆ ไหลผ่านแทนที่จะหยุดลูป

การอ่านแบบสโคปทั้งสองมีโปรไฟล์ต้นทุนที่ควรกล่าวถึง เปิดไฟล์หนึ่งครั้ง, สคีมหนึ่งชุด, ไม่ต้องเดินต้นไม้ ใส่ไว้ใน request handler หรือ gate; บันทึก snapshot เต็มรูปแบบสำหรับงาน ingestion ที่ต้องเก็บทุกอย่าง

ขั้นตอนที่ 3 — ตราประทับและแท็กโดยไม่เปิด Adobe

Writer จะสร้างสิ่งที่ขาดหายไปแบบ guard‑create ทำให้ปลอดภัยสำหรับการส่งออกใหม่ที่ไม่มีแพ็กเกจเลย

// Create missing layers, then write rights, creator, and CreatorTool
if (root.getXmpPackage() == null) {
    root.setXmpPackage(new XmpPacketWrapper());
}
if (root.getXmpPackage().getSchemes().getDublinCore() == null) {
    root.getXmpPackage().getSchemes().setDublinCore(new XmpDublinCorePackage());
}
XmpDublinCorePackage dc = root.getXmpPackage().getSchemes().getDublinCore();
dc.setRights(copyright);
dc.set("dc:creator", XmpArray.from(new String[]{creator}, XmpArrayType.Ordered));

if (root.getXmpPackage().getSchemes().getXmpBasic() == null) {
    root.getXmpPackage().getSchemes().setXmpBasic(new XmpBasicPackage());
}
root.getXmpPackage().getSchemes().getXmpBasic().setCreatorTool(creator);

metadata.save(outputPath);

คำสำคัญทำตามรูปแบบเดียวกันด้วยการเรียกครั้งเดียว เขียน bag ทั้งหมดเป็นอาเรย์ Unordered:

// Replace the dc:subject bag - merge in Java first for additive tagging
root.getXmpPackage().getSchemes().getDublinCore().set(
        "dc:subject", XmpArray.from(keywords, XmpArrayType.Unordered));
metadata.save(outputPath);

Main.java ปิดลูป: อ่านผลลัพธ์ใหม่และตรวจสอบว่าข้อความลิขสิทธิ์และคำสำคัญแรกยังคงอยู่หลังการบันทึก

การยืนยันตอนจบนี้ควรได้รับการสนับสนุน เมตาดาต้าเขียนอาจล้มเหลวโดยเงียบ ๆ; ไฟล์บันทึก, ไบต์เปลี่ยน, แต่ค่าที่คุณตั้งใจเขียนอาจไม่มีเพราะอ็อบเจ็กต์สคีมล้าสมัยหรือพาธชี้ไปที่ต้นฉบับ การอ่านกลับหลังการเขียนแต่ละครั้งเพิ่มการเปิดไฟล์หนึ่งครั้งต่อไฟล์และเปลี่ยน “สคริปต์ทำเสร็จ” เป็น “ค่ามีอยู่จริง” ซึ่งเป็นสิ่งที่เจ้าของคลังต้องการ เก็บไว้ใน production ไม่ใช่แค่ใน demo

คำสำคัญทำให้สินทรัพย์ค้นหาได้อย่างไรจริง ๆ?

เครื่องมือค้นหาไม่ได้อ่านพิกเซล; พวกมันอ่าน dc:subject Bridge, ดัชนี DAM, และแพลตฟอร์มสต็อกถือ bag นี้เป็นคำศัพท์ของสินทรัพย์ ดังนั้นไฟล์ที่ไม่มีคำสำคัญจะไม่ตรงกับการค้นหาเลย การเขียน bag เป็น Unordered XmpArray อย่างที่ AddKeywords ทำ คือสิ่งที่ทำให้สินทรัพย์จาก “ไม่มองเห็น” กลายเป็น “ค้นหาได้” และการเขียนใช้การบันทึกหนึ่งครั้ง

เปรียบเทียบข้างเคียง: ก่อน vs. หลัง

ก่อน (การแก้ไขผ่านแผง) หลัง (pipeline Java)
เครื่องมือ Photoshop หรือ Bridge ต่อไฟล์ หนึ่งโครงการ Maven, ไม่ต้องใช้ Adobe seat
การครอบคลุม ฟิลด์ที่แผงแสดง ทุกสคีมและแพ็กเกจของผู้ขาย
ความสามารถทำซ้ำ ขึ้นอยู่กับผู้ที่คลิก ลูปเดียวกัน, ผลลัพธ์เดียวกัน, ตรวจสอบได้
ไฟล์ที่ไม่มี XMP พฤติกรรมของแผงแตกต่างกัน Guard สร้างแพ็กเกจและสคีม
การตรวจสอบ เชื่อถือ อ่านกลับและยืนยันต่อไฟล์

ตัวอย่างจากโลกจริง: การส่งต่อจากเอเจนซี่

สตูดิโอรับไฟล์ PSD และ AI ผสมจากสามเอเจนซี่ แต่ละแห่งมีระเบียบเมตาดาต้าเป็นของตน งาน intake ตอนนี้รัน snapshot เมื่อไฟล์มาถึง, ทำเครื่องหมายไฟล์ที่ dc:rights ว่างเปล่า, ตราประทับด้วยบรรทัดสิทธิ์ตามสัญญา, และเขียนชุดคำสำคัญของแคมเปญ ลูปเดียวกันทำงานกับทั้งสองรูปแบบเพราะโค้ดไม่ได้อ้างอิงคอนเทนเนอร์ใด ๆ และเมตาดาต้า Adobe Illustrator ที่มาว่างเปล่าก็ยังทำให้ไฟล์ที่รับเข้ามามีแท็กและค้นหาได้

ผลต่อเนื่องที่สตูดิโอไม่คาดคิดคือสกอร์การ์ดของเอเจนซี่ เนื่องจากงาน intake บันทึกว่าการส่งมอบใดบ้างมาพร้อมฟิลด์สิทธิ์ว่าง Procurement จึงเห็นได้ว่า Supplier คนไหนส่งเมตาดาต้าสะอาดและคนไหนพึ่งพาลูกค้าแก้ไข การสนทนากับผู้ที่ทำผิดมากที่สุดใช้แค่ชาร์ตหนึ่งแผ่น

คุณสามารถทำอะไรเพิ่มเติมกับ GroupDocs.Metadata ได้บ้าง?

  • EXIF and IPTC in the same files: PSD มีมาตรฐานเมตาดาต้า 3 แบบ; ไลบรารีเดียวกันอ่านสองแบบที่เหลือผ่านแพ็กเกจของมันเอง ทำให้โปรไฟล์สินทรัพย์เต็มรูปแบบอยู่ห่างเพียงการอ่านเพิ่มอีกสองครั้ง
  • 170+ other formats: จุดเข้าของ Metadata เดียวกันให้บริการไฟล์ Office, PDF, audio, และ video ซึ่งทำให้งาน intake หนึ่งงานครอบคลุมคลังข้อมูลผสมทั้งหมด
  • Property search: findProperties กับ Specification สแกนไฟล์ใดก็ได้ตามเงื่อนไขที่คุณกำหนด ตั้งแต่การตรวจสอบสิทธิ์จนถึงการค้นหาฟิลด์กำหนดเอง

สรุป

สิ่งที่เคยเป็นขั้นตอนแผงต่อไฟล์เดี่ยวตอนนี้กลายเป็นสี่การดำเนินการใน Java: snapshot, อ่านแบบสโคป, ตราประทับความเป็นเจ้าของ, เขียนคำสำคัญ โค้ดเดียวกันทำงานกับไฟล์ PSD และ AI, guard ทำให้การส่งออกที่ว่างเปล่าปลอดภัย, และโครงการตัวอย่างที่ยืนยันแล้วพิสูจน์ชุดทั้งหมดก่อนคุณนำไปใช้กับคลังข้อมูลจริง

พร้อมที่จะยกเลิกการใช้แผง File Info หรือยัง?

แหล่งข้อมูลเพิ่มเติม