Search code examples
node.jssdkfetch-apicloudinary

Fetch file metadata from cloudinary using Node.js SDK


I'm building a website using React and storing my image assets on the cloudinary server. I want to create a scroll gallery with the image and a description.

Example:

// STATE

const [cloudImgData, fetchData] = useState([
{url: ['url string', ..], meta: ['metadata string']},
{url: ['url string', ..], meta: ['metadata string']},
...
])

const fetchIMGS = () => {
  //...fetch images
} 

return (
<div class="image_gallery">
  {cloudImgData.map((img) => {
    return (
      <img src={img.url}>
      <p>{img.meta}</p>
    )
  })}
</div>
)

For the backend I've been using the Nodejs SDK and its methods, I'm using the Admin and Metadata APIs.

const cloudinary = require('cloudinary').v2;
require('dotenv').config();

const getGalleryFromCloudinary = async (exhibit) => {
 
  try {

    const options = { 
      cloud_name: process.env.CLOUD_NAME,
      api_key: process.env.CLOUD_API,
      api_secret: process.env.CLOUD_SECRET_API,
      secure: true
    };

    cloudinary.config(options);

    // fetches URL
    const url = await cloudinary.api.resources({
      type: 'upload',
      prefix: 'prefix',
      max_results: 25,
      ...options
    });
    

   // EXPECTING
    /*
    RESPONSE object
 {
  "resources": [
    {
      "asset_id": "b1ce1d159bc3696e5a74d8b8aefbe707",
      "public_id": "face_center",
      "format": "jpg",
      "version": 1333013579,
      "resource_type": "image",
      "type": "upload",
      "created_at": "2012-03-29T09:32:59Z",
      "bytes": 128891,
      "width": 283,
      "height": 424,
      "backup": true,
      "access_mode": "public",
      "url": "http://res.cloudinary.com/demo/image/upload/v1333013579/face_center.jpg",
      "secure_url": "https://.../image/upload/v1333013579/face_center.jpg"
    },
    {
      "asset_id": "835d1cf89bd7c1b84dc4f53d35bc235f",
      "public_id": "12208495",
      "format": "jpg",
      "resource_type": "image",
      "type": "facebook",
      "created_at": "2012-10-06T17:18:52Z",
      "bytes": 0,
      "access_mode": "public",
      "url": "http://res.cloudinary.com/demo/image/facebook/12208495.jpg",
      "secure_url": "https://.../image/facebook/12208495.jpg"
    },
  ]
}
   */
    // ! SHOULD fetch metadata
    const meta = await cloudinary.api.list_metadata_fields(options);

   // EXPECTING 

  /*
{
  "metadata_fields": 
  [
    {
      "type": "date",
      "external_id": "available_date",
      "label": "Available date",
      "mandatory": false,
      "default_value": "2015-01-01",
      "validation": null,
      "default_disabled": false,
      "restrictions": {
        "readonly_ui": false
      }
    },
    {
      "type": "integer",
      "external_id": "in_stock",
      "label": "In stock",
      "mandatory": false,
      "default_value": 42,
      "validation": null,
      "default_disabled": false,
      "restrictions": {
        "readonly_ui": false
      }
    }
  ]
}
*/

      } catch (error) {
      console.error('error:', error);
  }
};
getGalleryFromCloudinary()

module.exports = getGalleryFromCloudinary;

I've added metadata to each image via the cloudinary gui:

enter image description here

MY GOAL: is the retrieve a list of metadata strings like the one I added: "California Horses #1", which serve as the image description

I HAVE 2 ISSUES:

  1. While the cloudinary.api.resources() DOES return the correct response object with the accompanying image urls. The cloudinary.api.list_metadata_fields() returns an empty array []. Does anyone have any expertise with the cloudinary SDK and might know why this is happening?

  2. Let's say I do manage to return the expected JSON object with the cloudinary.api.list_metadata_fields()...this won't mean that I'll be able to retrieve the "Californian Horses #1" title that I added to the image. Should this be the case...how can I add this string to any of the response objects?


Solution

  • list_metadata_fields() is a method relating to Structured metadata and its purpose is to return any Structured metadata field definitions you have created in your cloud. It will not return you details of assets from your cloud. https://cloudinary.com/documentation/metadata_api#get_metadata_fields

    In your example (screenshot), you are filling in the Contextual metadata of the asset and the resources() method returns details of assets from your cloud. You will get the Context metadata returned in the response only if you've passed the context parameter set to true in your resources() call options. E.g.

    const url = await cloudinary.api.resources({
      type: 'upload',
      prefix: '...',
      max_results: 500,
      context: true
    });
    

    Please see the Documentation for this method (https://cloudinary.com/documentation/admin_api#get_resources) which details all other parameters you can pass.

    You can also create Structured metadata fields and use those instead of Contextual metadata. Those are returned by default in the resources() response. Worth checking out the following section of the Documentation that details the difference between tags, context and structured metadata so that you can choose the best method of storing this data based on your requirements: https://cloudinary.com/documentation/dam_manage_individual_assets#custom_metadata_comparison_table

    The resources() method is part of the Admin API which should only be called from the server side since it relies on the API Secret which should be exposed only on the backend. Another option for getting details of assets (including metadata) could be using Resource Lists from the client side - with this feature, you can make a GET request which includes a shared tag as part of the URL and in the response, you'll get the details of assets which are tagged with the specified tag, including tags/context/structured metadata. This way, you avoid needing your server to make the request to Cloudinary to get the data and you can grab it from the client side directly.