Search code examples
springspring-bootimagefilecloudinary

Cloudinary Error: {"error":{"message":"Missing required parameter - timestamp"}}


I am trying to use Cloudinary's .downloadMulti(String tag, Map options) to generate a URL to download multiple images as a zip with the same tag. I am generating the URL seemingly just fine, but when I go to the URL, I am met with {"error":{"message":"Missing required parameter - timestamp"}}.

I've researched a bit and I saw that I need to sign the request, but it isn't saying that I'm missing that - just the timestamp. I believe the request is already being signed, just need a proper timestamp. I believe it needs to be within the constructor, but when I called Util.timestamp() it isn't recognized as a reference.

My Cloudinary initializer:

private final Cloudinary cloudinary = new Cloudinary(ObjectUtils.asMap(
            "cloud_name", "dxoa7bbix",
            "api_key", "161649288458746",
            "api_secret", "..."));

My upload method:

public Photo uploadOrderImage(String imageURL, String publicId, Order order, String photoType) throws IOException {
        Map result = cloudinary.uploader().upload(new File(imageURL), ObjectUtils.asMap(
                "public_id", publicId,
                 "tags", order.getId().toString()));
        Photo sellOrderPhoto = new Photo(
                result.get("secure_url").toString(),
                photoType,
                order
        );
        return photoRepository.save(sellOrderPhoto);
    }

This is my download method:

public String downloadPhotos(String tag) throws IOException {
        return cloudinary.downloadMulti(tag, ObjectUtils.asMap(
                "tags", tag
        ));
    }

An example URL my download method returns: Generated URL: https://api.cloudinary.com/v1_1/dxoa7bbix/image/multi?mode=download&async=false&signature=5f5da549fc78ea3fd50f034cdc76e2cce3089d48&api_key=161649288458746&tag=137×tamp=1638583257.

Overall, I think the problem is the lack of a timestamp. If you have any ideas, that would be great!


Solution

  • The reason for the error is that the parameter is expected to be called timestamp but based on the URL you shared, it is actually ×tamp.

    If you want to generate a URL to a ZIP file containing assets that share a particular tag, then you will want to use the generate_archive method and not multi which provides different functionality.

    If you replace the following code:

        return cloudinary.downloadMulti(tag, ObjectUtils.asMap(
            "tags", tag
        ));
    

    With:

        return cloudinary.downloadZip(ObjectUtils.asMap(
            "tags", tag, 
            "resource_type", "image")
        );
    

    Then that will generate and return a URL to a ZIP file that will get created when the URL is accessed and contain images from your cloud that contain the tag you specified.

    The Cloudinary Java SDK you're using will handle the signature/timestamp generation automatically when using any of the built-in methods, therefore, you don't need to make any changes to the SDK code or calculate the signature yourself if using the built-in methods. Signature generation is only necessary if you're not intending to use any of the SDKs but integrate with the Cloudinary API using your own custom code - such as if you're using a language for which a Cloudinary SDK doesn't yet exist. In such cases, if you want to perform authenticated API calls, you will need to generate authentication signatures yourself.