完整的工作範例可在 GitHub 上取得: edit-xmp-in-psd-and-ai-files-using-groupdocs-metadata-dotnet
生產挑戰:隱藏在無人注意之處的 Metadata
一家品牌工作室交付一個活動:分層的 PSD 主檔、AI 原始檔、數百個資產推送至客戶的 DAM。三週後,授權部門詢問誰擁有主圖像。答案其實存在,只是藏在電子郵件討論串中,因為檔案本身的 dc:rights 欄位為空。XMP 編輯是 GroupDocs.Metadata 在 .NET 上的功能,能在管線層面解決此類問題,直接在 PSD 與 AI 檔案內讀寫 XMP metadata 包,無需任何 Adobe 軟體介入。
規模問題悄然出現。設計師可以手動填寫 metadata 面板,仔細地做一段時間。但每季處理上千個資產的製作團隊無法如此操作,而每一次代理商、工作室與客戶之間的交接,都會讓未經驗證的 PSD metadata 檔案數量倍增。搜尋無法找到實際存在的資產。權利問題變成考古學,而考古學沒有服務等級協議(SLA)。
這些團隊真正需要的東西看起來像 API 規格:在 ingest 時快照檔案攜帶的所有資訊,在授權關卡檢查特定欄位,並在匯出時寫入所有權與關鍵字,且對兩種 Adobe 格式使用相同的程式碼。
現實檢驗:dc:rights 欄位為空的資產並非未授權,但下游任何人若找不到記得此事的同事,都無法證明其授權狀態。
為何常見的解決方案無法根本解決
團隊通常在正式自動化前會嘗試三種做法:
- 在 Photoshop 或 Bridge 手動編輯面板:每個檔案都能操作,但無法稽核,且需要 Adobe 授權才能執行本質上是資料輸入的工作。
- Sidecar 試算表:metadata 雖然存在,但一旦檔案被複製、重新命名或重新交付,就會與資產脫離。
- 自行解析:PSD 資源區塊與 AI 容器格式相當複雜,自製解析器在 Adobe 任意一次更新後就會變成維護負擔。
GroupDocs.Metadata 以單一 API 填補此缺口:將根封包轉型為 IXmp 後,即可對兩種格式的封包進行讀寫,此外還支援文件中列出的 170 多種其他封包,詳見 documentation。
解決方案:在管線中執行 XMP 操作
GroupDocs.Metadata for .NET 在資產管線的三個環節中發揮作用。於 ingest 時將完整封包快照存入資料庫的字典;於授權關卡讀取 Dublin Core(dc:rights 與 dc:creator 所屬的 schema);於匯出時寫入所有權與 dc:subject 關鍵字,若檔案根本沒有 XMP,則會自動建立缺失的 schema。我曾參與過太多次發佈回顧,根本原因都是資產缺少權利資料;設置關卡的目的正是因為回顧的成本遠高於讀取的成本。
實作前,您需要:
- .NET SDK 8.0 或更新版本
- GroupDocs.Metadata 26.6.0(取得臨時授權)
- 一個 PSD 或 AI 檔案以供實驗
dotnet add package GroupDocs.Metadata --version 26.6.0
companion repository 內提供了每種格式的範例檔案,並驗證以下每一步驟。
步驟式實作工作流程
步驟 1 – 在 Ingest 時快照全部資訊
一次遍歷即可捕獲封包、命名的 schema 以及任何供應商工具隱藏的資訊。將字典與資產記錄一起儲存,之後的問題就能直接透過資料庫查詢。
// Full XMP snapshot: packet, schemes, then a deep sweep
var result = new Dictionary<string, string>();
using (var metadata = new Metadata(adobeFilePath))
{
var root = metadata.GetRootPackage() as IXmp;
if (root?.XmpPackage == null) return result;
foreach (var property in root.XmpPackage)
{
result[property.Name] = property.InterpretedValue?.ToString()
?? property.Value?.ToString() ?? string.Empty;
}
// CollectScheme(...) repeats this loop for DublinCore, XmpBasic,
// Photoshop, CameraRaw, PagedText, XmpDynamicMedia, XmpMediaManagement
foreach (var p in metadata.FindProperties(p => p.Name != null))
{
if (!result.ContainsKey(p.Name))
{
result[p.Name] = p.InterpretedValue?.ToString()
?? p.Value?.ToString() ?? string.Empty;
}
}
}
return result;
InterpretedValue 會先被取用,因而日期與列舉值會以人類可讀的形式呈現。最後的 FindProperties 掃描則保證即使是插件自行寫入、未被任何已知 schema 覆蓋的 Adobe Illustrator metadata 也能完整收錄。
兩點運作注意事項:將快照以資產 ID 為鍵、以擷取日期為戳記儲存,因為檔案日後可能會變更,而快照即是「事前」的畫面。將空字典視為訊號而非錯誤;它會直接將資產送往蓋章步驟,而不是讓 ingest 失敗。
步驟 2 – 在授權關卡檢查 Dublin Core
九個 dc:* 欄位回答了法律與授權實務上真正關心的問題。只讀取該 schema 可讓關卡保持高速。
// dc:* fields only - Title, Creator, Rights, Subject and friends
var result = new Dictionary<string, string>();
using (var metadata = new Metadata(adobeFilePath))
{
var root = metadata.GetRootPackage() as IXmp;
var dc = root?.XmpPackage?.Schemes?.DublinCore;
if (dc == null) return result;
foreach (var property in dc)
{
result[property.Name] = property.InterpretedValue?.ToString()
?? property.Value?.ToString() ?? string.Empty;
}
}
return result;
為何這些設定對製作團隊至關重要:
- Null-conditional chain:沒有 XMP 的檔案在全新匯出時相當常見;空字典代表「請幫我蓋章」,而不是「程式當機」。
- Schema 範圍:關卡會在每一次資產移動時執行,僅讀取九個欄位而非整棵樹,可大幅降低成本。
步驟 3 – 在匯出時蓋章所有權
寫入動作會觸及三層結構,確保所有讀者(不論是否支援 XMP)看到相同的身份資訊。程式會先建立缺失的封包與 schema,再寫入資料。
// Guard-create the packet and scheme, then write rights and creator
using (var metadata = new Metadata(inputPath))
{
var root = metadata.GetRootPackage() as IXmp;
if (root == null) return;
if (root.XmpPackage == null)
root.XmpPackage = new XmpPacketWrapper();
if (root.XmpPackage.Schemes.DublinCore == null)
root.XmpPackage.Schemes.DublinCore = new XmpDublinCorePackage();
var dc = root.XmpPackage.Schemes.DublinCore;
dc.SetRights(copyright);
dc.Set("dc:creator", XmpArray.From(new[] { creator }, XmpArrayType.Ordered));
// Mirror the identity for XmpBasic readers and tag-classified fields
if (root.XmpPackage.Schemes.XmpBasic == null)
root.XmpPackage.Schemes.XmpBasic = new XmpBasicPackage();
root.XmpPackage.Schemes.XmpBasic.CreatorTool = creator;
metadata.SetProperties(p => p.Tags.Contains(Tags.Person.Creator),
new PropertyValue(creator));
metadata.Save(outputPath);
}
SetProperties 搭配 Tags.Person.Creator 的呼叫值得借鑒:它會更新庫中所有被歸類為 creator 的屬性,無論格式將其存放於何處,讓從未讀取過 XMP 的工具仍能顯示正確的作者名稱。
步驟 4 – 為搜尋寫入關鍵字
dc:subject 是 DAM 搜尋索引的詞彙表。若缺少此欄位,資產雖然存在卻永遠找不到。
// Replace the dc:subject bag with the pipeline's keyword list
root.XmpPackage.Schemes.DublinCore.Set(
"dc:subject",
XmpArray.From(keywords, XmpArrayType.Unordered));
metadata.Save(outputPath);
此寫入會取代既有的 bag,因此若要做累加標籤,需要先讀取、在 C# 中合併後再寫回。範例程式會寫入三個樣本關鍵字,並驗證第一個關鍵字會保留在儲存的位元組中。使用版本化分類法的團隊通常會為每個活動保存一套正規關鍵字,並在每次匯出時讓管線對照檔案進行調整,從而把關鍵字漂移變成差異(diff),而非爭論。
我們需要 Photoshop 授權才能修正 Metadata 嗎?
不需要,這正是自動化的目的所在。GroupDocs.Metadata 直接在 .NET 中讀寫封包,讓伺服器端工作可在不開啟任何 Adobe 應用程式的情況下,為整個檔案庫蓋章或修正關鍵字。設計師仍可保留自己的工具進行設計工作,而管線則負責大規模的 metadata 衛生。
這對業務有何改變
上述工作流程將三類常見事故轉變為非事件。權利問題不再需要依賴人力記憶,因為 dc:rights 會在關卡被檢查、缺失時即被蓋章。不可搜尋的資產不再累積,因為關鍵字由管線寫入,而非依賴臨時記得的人。且 metadata 工作不再佔用 Adobe 授權,因為四個步驟皆不會開啟設計工具。
此外,這也提供了手動編輯無法提供的稽核紀錄。每一次關卡決策與每一次蓋章都會留下程式碼路徑的日誌,當客戶詢問資產的權利來源時,答案就是一筆帶時間戳記的管線紀錄。整體僅有五個小方法,且在伴隨的範例庫中對 PSD 與 AI 各有一個樣本進行斷言,正是平台團隊在沒有專職維護者的情況下可以掌控的足跡。
結論
只要管線掌控 XMP metadata,PSD 與 AI 檔案的手動工作即告結束:在 ingest 時快照、在關卡檢查 Dublin Core、在匯出時蓋章所有權與關鍵字。一次 IXmp 轉型即可同時支援兩種格式,guard 機制讓全新匯出安全可寫,而本文示範的每項操作皆已在範例庫中斷言。
準備好將它接入您的管線了嗎?
- Clone the sample repository and run
dotnet run - Follow the technical deep-dive use case guide
- Read the Working with XMP metadata reference