Image/video dimensions (width/height/aspect ration)
I need to save the image /video dimensions (width /height /aspect ration ) in the database . so I use the input element in NC , upload the image /video , and before saving to database I need to fetch the image /video dimensions . has anyone implemented this before ? I tried with AI but was not successful . thanks I built [this ] ( https://editor.nordcraft.com/projects/seno12/branches/start/components/test-dimensions?rightpanel=style&selection=nodes.root&canvas-width=800&canvas-height=800 ) , but when I try to upload it returns {message : 'No files provided or invalid input . ' , details : { … } } so it looks like it 's this part of the custom action that the code is reaching , so perhaps you are not passing in the files correctly from the event ? if (!args || !Array.isArray(args.files) || args.files.length === 0) {
ctx.triggerActionEvent('On error', { message: 'No files provided or invalid input.', details: args });
return;
}I have to go into a meeting right now so if you dont ' get any further in an hour , I can look again but when a single file is uploaded , it 's not an array your files will be available at args.files.target.files in the custom action in the function getMediaDimensions however the rest of the code expects files to be an array , but it is an object here 's how I changed the getMediaDimensions formula in the custom action to not error https://editor.nordcraft.com/projects/_hite_ayla_secura_scra_ny_co_/branches/start/actions/getMediaDimensions?rightpanel=style hope that helps you on your way ! I 'm not sure where you got the code from for this custom action 🙂 @salma thanks this workd . just for future reference this is the code I used : / * * * A generic function to create a media processor . It handles the common logic * for loading a media element and extracting its dimensions . * @param {string } elementType - The type of element to create ( 'img ' or 'video ' ) . * @returns {function (File ) : Promise <object > } A function that takes a file and returns a promise with its dimensions . * / function createMediaProcessor (elementType ) { return function (file ) { return new Promise ( (resolve , reject ) = > { const element = document .createElement (elementType ) ; const url = URL .createObjectURL (file ) ; const loadEvent = elementType = = = 'img ' ? 'load ' : 'loadedmetadata ' ; / / Success handler element .addEventListener (loadEvent , ( ) = > { URL .revokeObjectURL (url ) ; const width = element .videoWidth element .naturalHeight ; resolve ( { fileName : file .name , width : width , height : height , / / Calculate aspect ratio on success aspect _ratio : height > 0 ? width / height : 0 , status : 'fulfilled ' } ) ; } ) ; / / Error handler element .addEventListener ( 'error ' , ( ) = > { URL .revokeObjectURL (url ) ; const fallbackWidth = 160 ; const fallbackHeight = 90 ; reject ( { fileName : file .name , width : fallbackWidth , height : fallbackHeight , / / Calculate aspect ratio for the fallback dimensions aspect _ratio : fallbackWidth / fallbackHeight , status : 'rejected ' , error : Failed to load ${elementType} metadata. } ) ; } ) ; element .src = url ; } ) ; } ; } / / Create specific processors from the generic function const processImageFile = createMediaProcessor ( 'img ' ) ; const processVideoFile = createMediaProcessor ( 'video ' ) ; / / A lookup map for routing file types to the correct processor const fileProcessors = { 'image ' : processImageFile , 'video ' : processVideoFile , } ; / * * * Main function to get media dimensions . * / async function getMediaDimensions (args , ctx ) { try { const fileList = args .files .target .files ; if ( !fileList | | !fileList .length ) { ctx .triggerActionEvent ( 'On error ' , { message : 'No files were provided . ' } ) ; return ; } const processingPromises = Array .from (fileList ) .map (file = > { const fileType = file .type .split ( ' / ' ) [0 ] ; const processor = fileProcessors [fileType ] ; if (processor ) { return processor (file ) ; } else { const fallbackWidth = 160 ; const fallbackHeight = 90 ; / / Add fallback dimensions and aspect ratio for unsupported files return Promise .resolve ( { fileName : file .name , width : fallbackWidth , height : fallbackHeight , aspect _ratio : fallbackWidth / fallbackHeight , status : 'rejected ' , error : 'Unsupported file type . ' } ) ; } } ) ; const results = await Promise .allSettled (processingPromises ) ; const mediaDimensions = results .map (result = > result .status = = = 'fulfilled ' ? result .value : result .reason ) ; ctx .triggerActionEvent ( 'On success ' , { mediaDimensions } ) ; } catch (error ) { ctx .triggerActionEvent ( 'On error ' , { message : 'A critical error occurred . ' , details : error .message } ) ; } }


