Larry Leonidas
Larry Leonidas

Reputation: 41

Cloudinary jQuery Upload Authorization

I'm using Force.com Apex and VF trying to utilize Cloudinary for some content management. I'm stuck on the following from Chrome (not sure why it shows 'undefined' as Cloud Name is defined in JS):

POST https://api.cloudinary.com/v1_1/undefined/upload 401 (Unauthorized)    ......    api.cloudinary.com/v1_1/undefined/upload:1

At a point of frustration would really appreciate any assistance. Here's the code (note comments):

:

public String getCldSig() {

        Datetime d = datetime.now();
        Long uxtime = d.getTime() / 1000; //method provides epoch/unix time
        String apisec = '<some_secret>';
        String serial = 'callback=<some_url>&public_id=<some_id>&timestamp=' + uxtime + apisec;
        Blob sha = Crypto.generateDigest('SHA1', Blob.valueOf(serial));
        String sig = EncodingUtil.convertToHex(sha); //perhaps I need to do UTF-8
        String jsoSerial = '{"public_id":"<some_Id>",';
        jsoSerial += '"timestamp":"'+ uxtime + '",'; 
        jsoSerial += '"callback":"<some_url>",';  //maybe an issue with hosting the CORS html on a VF page.
        jsoSerial += '"signature":"' + sig + '",'; 
        jsoSerial += '"api_key":"<some_key>"}';
        return jsoSerial.escapeHtml3(); //seems to be the right escape output HTML
}

Input HTML:

<input class="cloudinary-fileupload" 
data-cloudinary-field="upref" 
data-form-data="&quot;public_id&quot;:&quot;<some_id>&quot;,&quot;timestamp&quot;:&quot;1372282433&quot;,&quot;callback&quot;:&quot;<some_url>&quot;,&quot;signature&quot;:&quot;<some_sig>&quot;,&quot;api_key&quot;:&quot;<some_key>&quot;}" 
id="sceneUpload" 
name="file" 
type="file">

Upvotes: 1

Views: 2581

Answers (2)

Larry Leonidas
Larry Leonidas

Reputation: 41

With much help from Tal at Cloudinary, I have reached success! I'll recap the solution:

  1. Do not instantiate Cloudinary's library in $(document).ready(), instead just plug it in directly within script section

        <script type="text/javascript">             
        $.cloudinary.config({"api_key":"<key>","cloud_name":"<cloud_name>"});
    
  2. Instantiate the formData with the FileUpload widget, this ensures fileUpload
    loads your json send params (it's a timing issue).

                        $('.cloudinary-fileupload').fileupload({ 
                            formData : <unescaped json params>,
                            dropZone: $('.sceneUpBtn'),                             
                            dataType: 'json',
                            done: function (e, data) {
                                $.each(data.result.files, function (index, file) {
                                    $('<p/>').text(file.name).appendTo('#filename');
                                });
                                },
                            progressall: function (e, data) {
                                var progress = parseInt(data.loaded / data.total * 100, 10);
                                $('.sceneUpBar').css('width',progress + '%');
                            }
                    });
    
  3. Match signature params to json params sent to server. In Apex sign and return json as such:

    public String getCloudinarySig() {
        Datetime d = datetime.now();
        Long uxtime = d.getTime() / 1000; //epoch unix time method in force.com
        String apisec = '<secret>';
        String serial = 'callback=<cors url>&timestamp=' + uxtime + apisec; //Signature needs params here need to match json params below
        Blob sha = Crypto.generateDigest('SHA1', Blob.valueOf(serial)); //Sha1 digest
        String sig = EncodingUtil.convertToHex(sha); //Hex conversion
        String jsoSerial = '{';
        jsoSerial += '"api_key":"<key>",'; //these json params need to match signature params above     
        jsoSerial += '"<CORS_url>",';                   
        jsoSerial += '"signature":"' + sig + '",';  
        jsoSerial += '"timestamp":'+ uxtime; 
        jsoSerial += '}';
        return jsoSerial;       
    

    }

Happy to answer any questions...

Upvotes: 1

Tal Lev-Ami
Tal Lev-Ami

Reputation: 1457

The "undefined" part of the POST url means that Cloudinary's jQuery library could not determine the cloud_name when the POST url was generated. Most likely this is because the $.cloudinary.config function is called too late. Please move this call outside of $(document).ready or similar constructs.

One more (unrelated) point - The selector in the second line is missing a '.' It should read $('.cloudinary-fileupload')

Upvotes: 2

Related Questions