Reputation: 41
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>×tamp=' + 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
}
The Javascript/jQuery:
$.cloudinary.config({"api_key":"<some_key>", "cloud_name":"<some_id>"});
$('.cloudinary-fileupload')
.fileupload({
dropZone: ".sceneUpBtn",
progress: function (e, data) {
$(".progress").text("Uploading... " + Math.round((data.loaded * 100.0) / data.total) + "%");
}
});
$('.cloudinary-fileupload').bind('fileuploadstart', function(e){
$('.sceneUpPrev').html('Upload started...');
});
$('.cloudinary-fileupload').bind('fileuploadfail', function(e){
$('.sceneUpPrev').html($.cloudinary.error); //**due to lack of documentation don't know how to get any specific error message using the jQuery library. Would expect messages similar to AWS S3
});
$('.cloudinary-fileupload').bind('cloudinarydone', function(e, data) {
$('.sceneUpPrev').html(
$.cloudinary.image(data.result.public_id,
{ format: data.result.format, version: data.result.version,
crop: 'scale', width: 200 }));
$('.image_public_id').val(data.result.public_id);
return true;
});
Input HTML:
<input class="cloudinary-fileupload"
data-cloudinary-field="upref"
data-form-data=""public_id":"<some_id>","timestamp":"1372282433","callback":"<some_url>","signature":"<some_sig>","api_key":"<some_key>"}"
id="sceneUpload"
name="file"
type="file">
Upvotes: 1
Views: 2581
Reputation: 41
With much help from Tal at Cloudinary, I have reached success! I'll recap the solution:
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>"});
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 + '%');
}
});
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>×tamp=' + 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
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