Adobe Experience Manager Assets 開發人員使用案例、API和參考資料 assets-cloud-service-apis

本文包含適用於開發人員之建議、參考資料和資源, Assets as a Cloud Service. 其中包含新的資產上傳模組、API參考資料,以及有關後處理工作流程中所提供支援的資訊。

Experience Manager Assets API與作業 use-cases-and-apis

Assets as a Cloud Service 提供數個API,以程式設計方式與數位資產互動。 每個API都支援特定使用案例,如下表所述。 此 Assets 使用者介面, Experience Manager 案頭應用程式和 Adobe Asset Link 支援所有或部分作業。

CAUTION
有些API持續存在,但未主動支援(以×表示)。 請儘量不要使用這些API。
支援等級
說明
支援
×
不支援。 請勿使用。
-
無法使用
使用案例
aem-upload
Experience Manager / Sling / JCR Java API
asset compute服務
Assets HTTP API
Sling GET / POST servlet
GraphQL
原始二進位
建立原始檔案
×
-
×
×
-
讀取原始檔案
-
×
-
更新原始檔案
×
×
×
-
刪除原始檔案
-
-
-
複製原始檔案
-
-
-
移動原始檔案
-
-
-
中繼資料
建立中繼資料
-
-
讀取中繼資料
-
-
-
更新中繼資料
-
-
刪除中繼資料
-
-
複製中繼資料
-
-
-
移動中繼資料
-
-
-
內容片段(CF)
建立CF
-
-
-
-
讀取CF
-
-
-
更新CF
-
-
-
-
刪除CF
-
-
-
-
複製CF
-
-
-
-
移動CF
-
-
-
-
版本
建立版本
-
-
-
-
讀取版本
-
-
-
-
-
刪除版本
-
-
-
-
-
資料夾
建立資料夾
-
-
-
讀取資料夾
-
-
-
-
刪除資料夾
-
-
-
複製資料夾
-
-
-
行動資料夾
-
-
-

資產上傳 asset-upload

在 Experience Manager as a Cloud Service,您可以使用HTTP API直接將資產上傳到雲端儲存空間。 上傳二進位檔案的步驟如下。 在外部應用程式中執行這些步驟,而不是在 Experience Manager JVM。

  1. 提交HTTP要求. 它會通知 Experience Manage或部署您打算上傳新的二進位檔。
  2. PUT二進位檔的內容 初始化要求提供的一或多個URI。
  3. 提交HTTP要求 通知伺服器已成功上傳二進位檔的內容。

直接二進位上傳通訊協定概觀

IMPORTANT
在外部應用程式中而不是在 Experience Manager JVM。

方法提供可擴充且效能更高的資產上傳處理方式。 相較於以下的差異: Experience Manager 6.5為:

  • 二進位檔不會通過 Experience Manager,現在只需配合為部署設定的二進位雲端儲存空間來協調上傳程式。
  • 二進位雲端儲存空間可與內容傳遞網路(CDN)或邊緣網路搭配使用。 CDN會選取較接近使用者端的上傳端點。 當資料傳輸至附近端點的距離較短時,上傳效能和使用者體驗會改善,尤其是對於分散各地的團隊。
NOTE
請參閱使用者端代碼,以在開放原始碼中實施此方法 aem-upload資料庫.
IMPORTANT
在某些情況下,由於Experience Manager中儲存的最終一致性性質,變更可能不會在Cloud Service請求之間完全傳播。 這會導致404個起始或完成上傳呼叫的回應,因為必要的資料夾建立未傳播。 使用者端應該會收到404個回應,並透過實作附有後退策略的重試來處理這些回應。

啟動上傳 initiate-upload

將HTTPPOST請求提交到所需的資料夾。 資產會在此資料夾中建立或更新。 包含選擇器 .initiateUpload.json 指示要求要啟動二進位檔案的上傳。 例如,要建立資產的資料夾路徑為 /assets/folder. POST要求為 POST https://[aem_server]:[port]/content/dam/assets/folder.initiateUpload.json.

請求內文的內容型別應為 application/x-www-form-urlencoded 表單資料,包含下列欄位:

  • (string) fileName:必填。 資產在中出現的名稱 Experience Manager.
  • (number) fileSize:必填。 上傳資產的檔案大小(位元組)。

只要每個二進位檔案都包含必要欄位,就可以使用單一要求來起始多個二進位檔案的上傳。 如果成功,請求會回應 201 狀態代碼和包含下列格式JSON資料的內文:

{
    "completeURI": "(string)",
    "folderPath": "(string)",
    "files": [
        {
            "fileName": "(string)",
            "mimeType": "(string)",
            "uploadToken": "(string)",
            "uploadURIs": [
                "(string)"
            ],
            "minPartSize": (number),
            "maxPartSize": (number)
        }
    ]
}
  • completeURI (字串):當二進位檔完成上傳時,呼叫此URI。 URI可以是絕對URI或相對URI,使用者端應該能夠處理任一個。 也就是說,值可以是 "https://[aem_server]:[port]/content/dam.completeUpload.json""/content/dam.completeUpload.json" 另請參閱 完整上傳.
  • folderPath (字串):二進位檔案上傳所在資料夾的完整路徑。
  • (files) (陣列):其長度和順序符合起始請求中提供的二進位資訊清單長度和順序的元素清單。
  • fileName (字串):對應的二進位檔名稱,如起始要求中所提供。 此值應包含在完整請求中。
  • mimeType (字串):對應二進位檔的mime型別,如起始要求中所提供。 此值應包含在完整請求中。
  • uploadToken (字串):對應二進位檔案的上傳權杖。 此值應包含在完整請求中。
  • uploadURIs (陣列):字串清單,其值是二進位內容應上傳到的完整URI (請參閱 上傳二進位檔)。
  • minPartSize (數字):可提供給任一個資料庫之資料的最小長度(位元組)。 uploadURIs,如果有超過一個URI。
  • maxPartSize (數字):可提供給任一個的資料長度上限(位元組)。 uploadURIs,如果有超過一個URI。

上傳二進位檔 upload-binary

起始上傳的輸出包含一或多個上傳URI值。 如果提供了多個URI,使用者端可以依序將二進位分割成多個部分,並向提供的上傳URI提出每個部分的PUT請求。 如果您選擇將二進位檔案分割成零件,請遵循下列准則:

  • 除了最後一個零件外,每個零件的大小必須大於或等於 minPartSize.
  • 每個零件的大小必須小於或等於 maxPartSize.
  • 如果二進位檔案的大小超過 maxPartSize,將二進位檔案分割為多個部分以上傳。
  • 您不需要使用所有URI。

如果二進位檔的大小小於或等於 maxPartSize,您可以改為將整個二進位檔案上傳至單一上傳URI。 如果提供了多個上傳URI,請使用第一個並忽略其餘的URI。 您不需要使用所有URI。

CDN邊緣節點有助於加速要求的二進位檔上傳。

最簡單的實行方式是使用 maxPartSize 作為零件大小。 如果您使用此值作為部分大小,API合約可確保有足夠的上傳URI來上傳您的二進位檔。 若要這麼做,請將二進位分割成大小部分 maxPartSize,依序為每個零件使用一個URI。 最終零件的大小可小於或等於 maxPartSize. 例如,假設二進位檔案的總大小為20,000位元組, minPartSize 為5,000位元組, maxPartSize 為8,000位元組,而且上傳URI的數量為5。 執行以下步驟:

  • 使用第一個上傳URI上傳二進位的前8,000個位元組。
  • 使用第二個上傳URI上傳二進位檔案的第二個8,000位元組。
  • 使用第三個上傳URI上傳二進位檔案的最後4,000個位元組。 由於這是最後部分,因此不需要大於 minPartSize.
  • 您不需要使用最後兩個上傳URI。 您可以忽略它們。

常見的錯誤是根據API提供的上傳URI數量來計算零件大小。 API合約無法保證此方法有效,而且實際上可能會導致零件大小超出範圍 minPartSizemaxPartSize. 這可能會造成二進位上傳失敗。

同樣地,最簡單最安全的方法就是使用大小等於 maxPartSize.

如果上傳成功,伺服器會以回應每個要求 201 狀態代碼。

NOTE
如需上傳演演算法的詳細資訊,請參閱 正式功能檔案API檔案 Apache Jackrabbit Oak專案中的。

完成上傳 complete-upload

上傳二進位檔案的所有部分後,將HTTPPOST請求提交至初始化資料提供的完整URI。 請求內文的內容型別應為 application/x-www-form-urlencoded 表單資料,包含下列欄位。

欄位
類型
必要與否
說明
fileName
字串
必填
由初始資料提供的資產名稱。
mimeType
字串
必填
由起始資料提供的二進位檔的HTTP內容型別。
uploadToken
字串
必填
上傳二進位的Token,如初始化資料所提供。
createVersion
布林值
選用
如果 True 而且具有指定名稱的資產已存在,則 Experience Manager 會建立資產的新版本。
versionLabel
字串
選用
如果建立新版本,則會提供與資產新版本相關聯的標籤。
versionComment
字串
選用
如果建立了新版本,註釋會與該版本相關聯。
replace
布林值
選用
如果 True 而且具有指定名稱的資產已存在, Experience Manager 會刪除資產,然後重新建立資產。
uploadDuration
數字
選用
檔案完整上傳的總時間,以毫秒為單位。 如果指定,上傳持續時間會包含在系統的記錄檔中,以進行傳輸率分析。
fileSize
數字
選用
檔案的大小(位元組)。 如果指定,檔案大小會包含在系統的記錄檔中,以進行傳輸速率分析。
NOTE
如果資產存在,但兩者皆非 createVersion 也不 replace 已指定,則 Experience Manager 以新的二進位檔案更新資產的目前版本。

如同起始程式,完整的請求資料可能包含多個檔案的資訊。

在呼叫檔案的完整URL之前,不會完成上傳二進位檔的程式。 資產會在上傳程式完成後處理。 即使資產的二進位檔案已完全上傳,但上傳程式未完成,處理作業也不會開始。 如果上傳成功,伺服器會以回應 200 狀態代碼。

將資產上傳至AEMas a Cloud Service的範例殼層指令碼 upload-assets-shell-script

以下範例shell-script說明在AEMas a Cloud Service中直接二進位存取的多步驟上傳程式 aem-upload.sh

#!/bin/bash

# Check if pv is installed
if ! command -v pv &> /dev/null; then
    echo "Error: 'pv' command not found. Please install it before running the script."
    exit 1
fi

# Check if jq is installed
if ! command -v jq &> /dev/null; then
    echo "Error: 'jq' command not found. Please install it before running the script."
    exit 1
fi

# Set DEBUG to true to enable debug statements
DEBUG=true

# Function for printing debug statements
function debug() {
    if [ "${DEBUG}" = true ]; then
        echo "[DEBUG] $1"
    fi
}

# Function to check if a file exists
function file_exists() {
    [ -e "$1" ]
}

# Function to check if a path is a directory
function is_directory() {
    [ -d "$1" ]
}

# Check if the required number of parameters are provided
if [ "$#" -ne 4 ]; then
    echo "Usage: $0 <aem-url> <asset-folder> <file-to-upload> <bearer-token>"
    exit 1
fi

AEM_URL="$1"
ASSET_FOLDER="$2"
FILE_TO_UPLOAD="$3"
BEARER_TOKEN="$4"

# Extracting file name or folder name from the file path
NAME=$(basename "${FILE_TO_UPLOAD}")

# Step 1: Check if "file-to-upload" is a folder
if is_directory "${FILE_TO_UPLOAD}"; then
    echo "Uploading files from the folder recursively..."

    # Recursively upload files in the folder
    find "${FILE_TO_UPLOAD}" -type f | while read -r FILE_PATH; do
        FILE_NAME=$(basename "${FILE_PATH}")
        debug "Uploading file: ${FILE_PATH}"

        # You can choose to initiate upload for each file here
        # For simplicity, let's assume you use the same ASSET_FOLDER for all files
        ./aem-upload.sh "${AEM_URL}" "${ASSET_FOLDER}" "${FILE_PATH}" "${BEARER_TOKEN}"
    done
else
    # "file-to-upload" is a single file
    FILE_NAME="${NAME}"

    # Step 2: Calculate File Size
    FILE_SIZE=$(stat -c %s "${FILE_TO_UPLOAD}")

    # Step 3: Initiate Upload
    INITIATE_UPLOAD_ENDPOINT="${AEM_URL}/content/dam/${ASSET_FOLDER}.initiateUpload.json"

    debug "Initiating upload..."
    debug "Initiate Upload Endpoint: ${INITIATE_UPLOAD_ENDPOINT}"
    debug "File Name: ${FILE_NAME}"
    debug "File Size: ${FILE_SIZE}"

    INITIATE_UPLOAD_RESPONSE=$(curl -X POST \
        -H "Authorization: Bearer ${BEARER_TOKEN}" \
        -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
        -d "fileName=${FILE_NAME}" \
        -d "fileSize=${FILE_SIZE}" \
        ${INITIATE_UPLOAD_ENDPOINT})

    # Continue with the rest of the script...
fi


# Check if the response body contains the specified HTML content for a 404 error
if echo "${INITIATE_UPLOAD_RESPONSE}" | grep -q "<title>404 Specified folder not found</title>"; then
    echo "Folder not found. Creating the folder..."

    # Attempt to create the folder
    CREATE_FOLDER_ENDPOINT="${AEM_URL}/api/assets/${ASSET_FOLDER}"

    debug "Creating folder..."
    debug "Create Folder Endpoint: ${CREATE_FOLDER_ENDPOINT}"

    CREATE_FOLDER_RESPONSE=$(curl -X POST \
        -H "Content-Type: application/json" \
        -H "Authorization: Bearer ${BEARER_TOKEN}" \
        -d '{"class":"'${ASSET_FOLDER}'","properties":{"title":"'${ASSET_FOLDER}'"}}' \
        ${CREATE_FOLDER_ENDPOINT})

    # Check the response code and inform the user accordingly
    STATUS_CODE_CREATE_FOLDER=$(echo "${CREATE_FOLDER_RESPONSE}" | jq -r '.properties."status.code"')
    case ${STATUS_CODE_CREATE_FOLDER} in
        201)
            echo "Folder created successfully. Initiating upload again..."

            # Retry Initiate Upload after creating the folder
            INITIATE_UPLOAD_RESPONSE=$(curl -X POST \
                -H "Authorization: Bearer ${BEARER_TOKEN}" \
                -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
                -d "fileName=${FILE_NAME}" \
                -d "fileSize=${FILE_SIZE}" \
                ${INITIATE_UPLOAD_ENDPOINT})
            ;;
        409)
            echo "Error: Folder already exists."
            ;;
        412)
            echo "Error: Precondition failed. Root collection cannot be found or accessed."
            exit 1
            ;;
        500)
            echo "Error: Internal Server Error. Something went wrong."
            exit 1
            ;;
        *)
            echo "Error: Unexpected response code ${STATUS_CODE_CREATE_FOLDER}"
            exit 1
            ;;
    esac
fi

# Extracting values from the response
FOLDER_PATH=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.folderPath')
UPLOAD_URIS=($(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.files[0].uploadURIs[]'))
UPLOAD_TOKEN=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.files[0].uploadToken')
MIME_TYPE=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.files[0].mimeType')
MIN_PART_SIZE=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.files[0].minPartSize')
MAX_PART_SIZE=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.files[0].maxPartSize')
COMPLETE_URI=$(echo "${INITIATE_UPLOAD_RESPONSE}" | jq -r '.completeURI')

# Extracting "Affinity-cookie" from the response headers
AFFINITY_COOKIE=$(echo "${INITIATE_UPLOAD_RESPONSE}" | grep -i 'Affinity-cookie' | awk '{print $2}')

debug "Folder Path: ${FOLDER_PATH}"
debug "Upload Token: ${UPLOAD_TOKEN}"
debug "MIME Type: ${MIME_TYPE}"
debug "Min Part Size: ${MIN_PART_SIZE}"
debug "Max Part Size: ${MAX_PART_SIZE}"
debug "Complete URI: ${COMPLETE_URI}"
debug "Affinity Cookie: ${AFFINITY_COOKIE}"
if $DEBUG; then
    i=1
    for UPLOAD_URI in "${UPLOAD_URIS[@]}"; do
        debug "Upload URI $i: "$UPLOAD_URI
        i=$((i+1))
    done
fi


# Calculate the number of parts needed
NUM_PARTS=$(( (FILE_SIZE + MAX_PART_SIZE - 1) / MAX_PART_SIZE ))
debug "Number of Parts: $NUM_PARTS"

# Calculate the part size for the last chunk
LAST_PART_SIZE=$(( FILE_SIZE % MAX_PART_SIZE ))
if [ "${LAST_PART_SIZE}" -eq 0 ]; then
    LAST_PART_SIZE=${MAX_PART_SIZE}
fi

# Step 4: Upload binary to the blob store in parts
PART_NUMBER=1
for i in $(seq 1 $NUM_PARTS); do
    PART_SIZE=${MAX_PART_SIZE}
    if [ ${PART_NUMBER} -eq ${NUM_PARTS} ]; then
        PART_SIZE=${LAST_PART_SIZE}
        debug "Last part size: ${PART_SIZE}"
    fi

    PART_FILE="/tmp/${FILE_NAME}_part${PART_NUMBER}"

    # Creating part file
    SKIP=$((PART_NUMBER - 1))
    SKIP=$((MAX_PART_SIZE * SKIP))
    dd if="${FILE_TO_UPLOAD}" of="${PART_FILE}"  bs="${PART_SIZE}" skip="${SKIP}" count="${PART_SIZE}" iflag=skip_bytes,count_bytes  > /dev/null 2>&1
    debug "Creating part file: ${PART_FILE} with size ${PART_SIZE}, skipping first ${SKIP} bytes."


    UPLOAD_URI=${UPLOAD_URIS[$PART_NUMBER-1]}

    debug "Uploading part ${PART_NUMBER}..."
    debug "Part Size: $PART_SIZE"
    debug "Part File: ${PART_FILE}"
    debug "Part File Size: $(stat -c %s "${PART_FILE}")"
    debug "Upload URI: ${UPLOAD_URI}"

    # Upload the part in the background
    if command -v pv &> /dev/null; then
        pv "${PART_FILE}" | curl --progress-bar -X PUT --data-binary "@-" "${UPLOAD_URI}" &
    else
        curl -# -X PUT --data-binary "@${PART_FILE}" "${UPLOAD_URI}" &
    fi

    PART_NUMBER=$((PART_NUMBER + 1))
done

# Wait for all background processes to finish
wait

# Step 5: Complete the upload in AEM
COMPLETE_UPLOAD_ENDPOINT="${AEM_URL}${COMPLETE_URI}"

debug "Completing the upload..."
debug "Complete Upload Endpoint: ${COMPLETE_UPLOAD_ENDPOINT}"

RESPONSE=$(curl -X POST \
    -H "Authorization: Bearer ${BEARER_TOKEN}" \
    -H "Content-Type: application/x-www-form-urlencoded; charset=UTF-8" \
    -H "Affinity-cookie: ${AFFINITY_COOKIE}" \
    --data-urlencode "uploadToken=${UPLOAD_TOKEN}" \
    --data-urlencode "fileName=${FILE_NAME}" \
    --data-urlencode "mimeType=${MIME_TYPE}" \
    "${COMPLETE_UPLOAD_ENDPOINT}")

debug $RESPONSE

echo "File upload completed successfully."

開放原始碼上傳程式庫 open-source-upload-library

若要深入瞭解上傳演演算法,或若要建置您自己的上傳指令碼和工具,Adobe提供開放原始碼程式庫和工具:

NOTE
aem-upload程式庫和命令列工具都會使用 node-httptransfer程式庫

已棄用的資產上傳API deprecated-asset-upload-api

只有以下專案才支援新的上傳方法 Adobe Experience Manager as a Cloud Service. 來自的API Adobe Experience Manager 6.5已過時。 下列API中不建議使用與上傳或更新資產或轉譯(任何二進位上傳)相關的方法:

  • EXPERIENCE MANAGER ASSETS HTTP API
  • AssetManager Java API,例如 AssetManager.createAsset(..)AssetManager.createAssetForBinary(..)AssetManager.getAssetForBinary(..)AssetManager.removeAssetForBinary(..)AssetManager.createOrUpdateAsset(..)AssetManager.createOrReplaceAsset(..)

資產處理和後續處理工作流程 post-processing-workflows

在 Experience Manager,資產處理會根據 處理設定檔 使用的設定 資產微服務. 處理不需要開發人員擴充功能。

若要設定後續處理工作流程,請將標準工作流程與擴充功能搭配使用,並搭配自訂步驟。

支援後處理工作流程中的工作流程步驟 post-processing-workflows-steps

如果您從舊版升級 Experience Manager,您可以使用資產微服務來處理資產。 雲端原生資產微服務可更輕鬆設定和使用。 中使用的幾個工作流程步驟 DAM更新資產 不支援舊版的工作流程。 如需有關支援類別的詳細資訊,請參閱 Java API參考或Javadocs.

以下技術工作流程模型已由資產微服務取代,或無法提供支援:

  • com.day.cq.dam.cameraraw.process.CameraRawHandlingProcess
  • com.day.cq.dam.core.process.CommandLineProcess
  • com.day.cq.dam.pdfrasterizer.process.PdfRasterizerHandlingProcess
  • com.day.cq.dam.core.process.AddPropertyWorkflowProcess
  • com.day.cq.dam.core.process.CreateSubAssetsProcess
  • com.day.cq.dam.core.process.DownloadAssetProcess
  • com.day.cq.dam.word.process.ExtractImagesProcess
  • com.day.cq.dam.word.process.ExtractPlainProcess
  • com.day.cq.dam.ids.impl.process.IDSJobProcess
  • com.day.cq.dam.indd.process.INDDMediaExtractProcess
  • com.day.cq.dam.indd.process.INDDPageExtractProcess
  • com.day.cq.dam.core.impl.lightbox.LightboxUpdateAssetProcess
  • com.day.cq.dam.pim.impl.sourcing.upload.process.ProductAssetsUploadProcess
  • com.day.cq.dam.core.process.SendDownloadAssetEmailProcess
  • com.day.cq.dam.similaritysearch.internal.workflow.smarttags.StartTrainingProcess
  • com.day.cq.dam.similaritysearch.internal.workflow.smarttags.TransferTrainingDataProcess
  • com.day.cq.dam.switchengine.process.SwitchEngineHandlingProcess
  • com.day.cq.dam.core.process.GateKeeperProcess
  • com.day.cq.dam.s7dam.common.process.DMEncodeVideoWorkflowCompletedProcess
  • com.day.cq.dam.core.process.DeleteImagePreviewProcess
  • com.day.cq.dam.video.FFMpegTranscodeProcess
  • com.day.cq.dam.core.process.ThumbnailProcess
  • com.day.cq.dam.video.FFMpegThumbnailProcess
  • com.day.cq.dam.core.process.CreateWebEnabledImageProcess
  • com.day.cq.dam.core.process.CreatePdfPreviewProcess
  • com.day.cq.dam.s7dam.common.process.VideoUserUploadedThumbnailProcess
  • com.day.cq.dam.s7dam.common.process.VideoThumbnailDownloadProcess
  • com.day.cq.dam.s7dam.common.process.VideoProxyServiceProcess
  • com.day.cq.dam.scene7.impl.process.Scene7UploadProcess
  • com.day.cq.dam.s7dam.common.process.S7VideoThumbnailProcess
  • com.day.cq.dam.core.process.MetadataProcessorProcess
  • com.day.cq.dam.core.process.AssetOffloadingProcess
  • com.adobe.cq.dam.dm.process.workflow.DMImageProcess

另請參閱

recommendation-more-help
fbcff2a9-b6fe-4574-b04a-21e75df764ab