مثال عملي كامل متاح على GitHub:
read-and-write-xmp-in-psd-ai-files-java

الطريقة القديمة كانت مؤلمة

تخيل عملية تنظيف الأرشيف التي لا يتطوع أحد للقيام بها. مجلد يحتوي على ملفات PSD رئيسية ومصادر AI يحتاج إلى إشعارات حقوق وكلمات مفتاحية قبل أن يدخل نظام DAM. الروتين: فتح ملف في Photoshop، فتح معلومات الملف، كتابة حقوق النشر، كتابة الكلمات المفتاحية، حفظ، إغلاق، الملف التالي. كل عملية حفظ تعيد تصيير الملف الطبقي فقط لتغيير بعض سلاسل بيانات XMP. الأرشيف الذي علمني هذا الدرس كان مجلدًا من ملفات Illustrator غير مُوسومة لا يستطيع أحد البحث فيها؛ أصلحنا الأمر بحلقة، ليس بالمزيد من الصبر.

إذا ضاعفت هذا الروتين على مستوى الأرشيف، يتوقف عن كونه مهمة ويصبح مشروعًا. والأسوأ، أنه غير قابل للتدقيق: لا أحد يستطيع إثبات ما تم إنجازه لاحقًا، والملفات التي تم تخطيها تبدو متطابقة حتى تظهر مسألة ترخيص. طريقة اللوحة تربط إدخال البيانات بأدوات التصميم بهدوء. من يحتاج إلى تعديل البيانات الوصفية يحتاج إلى ترخيص Adobe، ومحطة عمل تفتح الملفات الطبقية بسهولة، وصبر ينتظر عمليات الحفظ التي تعيد تصيير العمل فقط لتغيير سلاسل.

التكلفة الحقيقية للقيام بذلك يدويًا: البيانات الوصفية التي تُعد يدويًا هي بيانات لا يمكن لأحد التحقق منها لاحقًا؛ العملية لا تترك أي أثر سوى المصممين المتعبين.

هناك طريقة أفضل

GroupDocs.Metadata للـ Java يقرأ ويكتب حزمة XMP مباشرة. قم بتحويل getRootPackage() إلى IXmp وستكون الحزمة، المخططات، والمصفوفات كائنات Java عادية، متطابقة لملفات PSD وAI، دون الحاجة إلى أي برنامج Adobe. الوثائق (documentation) تسرد أكثر من 170 تنسيقًا خلف نفس الـ API.

قبل أن نبدأ، ستحتاج إلى:

أضف الاعتماد ومستودع GroupDocs إلى ملف pom.xml الخاص بك:

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

المستودع المرافق (companion repository) يضم pom.xml جاهزًا بالإضافة إلى عينات من كلا التنسيقين، ويؤكد كل خطوة أدناه.

الطريقة الجديدة: أربع عمليات في Java

الخطوة 1 – رؤية ما يحمله الملف

تلتقط اللقطة الحزمة وكل مخطط في خريطة 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() لتصبح التواريخ قابلة للقراءة، وتلتقط عملية المسح المدفوعة بالمواصفات حزم البائع. نسخة المستودع تتعامل مع سبعة مخططات؛ الشكل يبقى نفسه.

الخطوة 2 – قراءة الحقول التي تجيب على الأسئلة

الترخيص يسأل عن dc:rights. البحث يهتم بـ dc:subject. كلاهما في Dublin Core، والقراءة المحددة تكلف تسعة حقول فقط، لا مشي شجرة.

// 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 بنفس الطريقة عبر getters المكتوبة (getCity(), getCredit(), getColorMode() وغيرها الخمسة)، لتغطية حقول بيانات PSD التي تقرأها فلاتر Bridge وLightroom. في المستودع يلف القارئ كل getter بمساعدة آمنة من الـ null، لذا الملف القليل البيانات يُعيد سلاسل فارغة بدلًا من مفاجآت. هذا التفصيل مهم أكثر مما يبدو: الهدف من أتمتة الأرشيف هو أن تمر الملفات الغريبة دون إيقاف الحلقة.

كلا القراء المحددين يشتركان في نموذج تكلفة يستحق الذكر. فتح ملف واحد، مخطط واحد، لا مشي شجرة. ضعها في معالجات الطلبات والبوابات؛ احفظ اللقطة الكاملة لوظائف الاستيعاب التي تخزن كل شيء.

الخطوة 3 – ختم ووضع علامة دون فتح Adobe

الكتّاب يخلقون أي شيء مفقود، مما يجعلهم آمنين للتصدير الجديد الذي لا يحمل حزمة على الإطلاق.

// 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);

الكلمات المفتاحية تتبع نفس النمط بند واحد، تكتب الحقيبة بالكامل كمصفوفة غير مرتبة:

// 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 يغلق الحلقة: يعيد قراءة المخرجات ويؤكد أن سلسلة حقوق النشر والكلمة المفتاحية الأولى نجحت في الحفظ.

هذا التأكيد يستحق جملة من الدعوة. عمليات كتابة البيانات الوصفية تفشل بصمت عندما تفشل؛ الملف يُحفظ، البايتات تتغير، والقيمة التي قصدت كتابتها ببساطة لا تكون موجودة لأن كائن المخطط كان قديمًا أو المسار أشار إلى الأصل. قراءة ما بعد كل كتابة تكلف فتحًا إضافيًا لكل ملف وتحوّل “انتهى السكربت” إلى “القيم موجودة”، وهو ما يريده مالك الأرشيف فعليًا. احتفظ به في الإنتاج، لا في العرض التجريبي فقط.

كيف تجعل الكلمات المفتاحية الأصول قابلة للبحث فعليًا؟

أدوات البحث لا تقرأ البكسلات؛ إنها تقرأ dc:subject. Bridge، فهارس DAM، ومنصات المخزون تعتبر تلك الحقيبة مفردات الأصل، لذا الملف بدون كلمات مفتاحية لا يطابق أي استعلام. كتابة الحقيبة كمصفوفة XmpArray غير مرتبة، كما تفعل AddKeywords، هو ما ينقل الأصل من غير مرئي إلى قابل للعثور، وتكلفة الكتابة هي حفظ واحد.

مقارنة جنبًا إلى جنب: قبل vs. بعد

قبل (تحرير عبر اللوحة) بعد (خط أنابيب Java)
الأدوات Photoshop أو Bridge لكل ملف مشروع Maven واحد، لا حاجة لترخيص Adobe
التغطية الحقول التي تظهر في اللوحة كل مخطط بالإضافة إلى حزم البائع
قابلية التكرار تعتمد على من نقر نفس الحلقة، نفس النتيجة، قابل للتدقيق
ملفات بدون XMP سلوك اللوحة متقلب الحراس يخلقون الحزمة والمخططات
التحقق ثقة قراءة مؤكدة بعد كل ملف

صف صف التحقق يقرر الأمر للأرشيفات: سكربت يثبت كتاباته هو الفارق بين “قمنا بوضع العلامات على الملفات” و"يمكننا إظهار ذلك لك".

مثال واقعي: تسليم الوكالة

ستوديو يستقبل تسليمات مختلطة من PSD وAI من ثلاث وكالات، كل منها يتبع نهجًا مختلفًا للبيانات الوصفية. الآن مهمة الاستقبال تقوم بالتقاط اللقطة عند الوصول، تُعلم الملفات التي تكون قيمة dc:rights فيها فارغة، تختمها بسطر الحقوق المتعاقد عليها، وتكتب مجموعة كلمات المفتاح الخاصة بالحملة. نفس الحلقة تخدم كلا التنسيقين لأن الكود لا يذكر نوع الحاوية، وبيانات Illustrator التي تصل فارغة تظل مُوسومة وقابلة للبحث.

الأثر المتتابع هو ما لم يتوقعه الستوديو: بطاقات تقييم الوكالات. لأن مهمة الاستقبال تسجل أي تسليم وصل بحقوق فارغة، يلاحظ قسم الشراء أي الموردين يرسلون بيانات وصفية نظيفة وأيهم يعتمد على العميل لتصحيحها. المحادثة مع الأسوأ استغرقت مخططًا واحدًا.

ماذا يمكنك أن تفعل أيضًا مع GroupDocs.Metadata؟

  • EXIF و IPTC في نفس الملفات: ملفات PSD تحمل ثلاثة معايير للبيانات الوصفية؛ المكتبة نفسها تقرأ الاثنين الآخرين عبر حزمهم، لذا ملف تعريف الأصل الكامل يبعد قراءتين إضافيتين.
  • أكثر من 170 تنسيقًا آخر: نقطة الدخول المتطابقة Metadata تخدم ملفات Office، PDF، الصوت، والفيديو، وهذا هو السبب في أن مهمة استلام واحدة تغطي أرشيفًا مختلطًا بالكامل.
  • بحث عن الخصائص: findProperties مع Specification يمسح أي ملف لأي شرط تحدده، من فحص الحقوق إلى صيد الحقول المخصصة.

الخلاصة

ما كان روتينًا عبر لوحة لكل ملف أصبح الآن أربع عمليات Java: لقطة، قراءة محددة، ختم ملكية، كتابة كلمات مفتاحية. نفس الكود يخدم ملفات PSD وAI، الحراس يجعلون الصادرات الفارغة آمنة، وعينة المشروع المؤكدة تثبت كل شيء قبل توجيهها إلى أرشيف حقيقي.

هل أنت مستعد للتخلي عن لوحة معلومات الملف؟

موارد إضافية