Created
November 10, 2023 08:31
-
-
Save rwunsch/f72692a9a1bb99d2906918e518a6324d to your computer and use it in GitHub Desktop.
AEMaaCS - AEM as a Cloud Services - File and Folder upload shell script ( initiateUpload , uploadToken , fileName , mimeType )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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 URIs: ${UPLOAD_URIS[@]}" | |
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}" | |
# Calculate the number of parts needed | |
NUM_PARTS=$(( (FILE_SIZE + MAX_PART_SIZE - 1) / MAX_PART_SIZE )) | |
# 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 UPLOAD_URI in "${UPLOAD_URIS[@]}"; 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}" | |
# Check if the part file already exists | |
if file_exists "${PART_FILE}"; then | |
debug "Using existing part file: ${PART_FILE}" | |
else | |
dd if="${FILE_TO_UPLOAD}" of="${PART_FILE}" bs=${PART_SIZE} count=1 2>/dev/null | |
debug "Creating part file: ${PART_FILE}" | |
fi | |
debug "Uploading part ${PART_NUMBER}..." | |
debug "Part File: ${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}" | |
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}" | |
echo "File upload completed successfully." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment