Issue
Cloudinary have a basic.js
example which I'm trying to implement in my Ionic/Angular project.
Problem is, for some reason the Ionic version of "@cloudinary/angular-5.x" always uses the unsigned_upload
feature, and I want to be able to transform it before I upload, same as the Cloudinary example.
Transformation requires signed
upload not unsigned
upload.
Since there are many versions out-there, and most of the examples don't work, mine is:
Ionic: 3
Angular: 5.2.11
Cloudinary:
"cloudinary": "^1.11.0",
"cloudinary-core": "^2.5.0",
"@cloudinary/angular-5.x": "^1.0.2"
basic.js
My configuration is inside the .env variable with the structure mentioned in cloudinary.config
var dotenv = require('dotenv');
dotenv.load();
var fs = require('fs');
var cloudinary = require('cloudinary').v2;
// set your env variable CLOUDINARY_URL or set the following configuration
/*cloudinary.config({
cloud_name: '',
api_key: '',
api_secret: ''
});*/
var url = "http://res.cloudinary.com/demo/image/upload/couple.jpg"
cloudinary.uploader.upload(url,{"tags":"basic_sample","width":500,"height":500,"crop":"fit","effect":"saturation:-70"} ,
function(err,image){
if (err){
console.warn(err);
return;
}
console.log("* "+image.public_id);
console.log("* "+image.url);
// Transform image
cloudinary.url(image.public_id,
{
width: 200,
height: 150,
crop: "fill",
gravity: "face",
radius: 10,
effect:"sepia",
format: "jpg"
}
));
});
I'm able with the following code to upload it unsigned
Ionic unsigned request
ngOnInit(): void {
const uploaderOptions: FileUploaderOptions = {
url: 'https://api.cloudinary.com/v1_1/' + this.cloudinary.config().cloud_name + '/upload',
autoUpload: false,
isHTML5: true,
removeAfterUpload: true,
headers: [{
name: 'X-Requested-With',
value: 'XMLHttpRequest'
}]
};
this.uploader = new FileUploader(uploaderOptions);
// Add custom tag for displaying the uploaded photo in the list
this.uploader.onBuildItemForm = (fileItem: any, form: FormData): any => {
form.append('upload_preset', this.cloudinary.config().upload_preset);
form.append('public_id', 'subfolder/' + this.UUID);
form.append('file', fileItem);
fileItem.withCredentials = false;
return { fileItem, form };
};
}
Ionic signed request
So in order to transform my images, I need to use parameter called eager
form.append('eager', 'c_crop,w_191,h_145,g_face,z_0.7');
But then I get the below error
Upload completed with status code 400
{
"message": "Eager parameter is not allowed when using unsigned upload.
Only upload_preset,callback,public_id,folder,tags,context,face_coordinates,custom_coordinates,source upload parameters are allowed.
}
When I remove the preset to "tell" it that maybe this is a signed request, I get the above error + Upload preset must be specified when using unsigned upload
So I'm not sure how I'm suppose to "tell" it - use signed request, and take my configuration from .env
or CloudinaryModule.forRoot({Cloudinary}, cloudinaryConfiguration as CloudinaryConfiguration),
etc ...
Solution
For signed upload, you need to create a signature. During post request, you have to attach it with form.
Signature is SHA1 hexadecimal string which is consists of timestamp(unixtime), public_id (any text) and your cloudinary API_SECRET.
Here is my workable sample
private generateSignature() {
this.public_id = `image_${Date.now()}`; // I like to make it unique.
this.unixtime = Date.now() / 1000 | 0;
return CryptoJS.SHA1(`public_id=${this.public_id}×tamp=${this.unixtime}${this.API_SECRET}`).toString()
}
here I use CryptoJS for encription.
Append this signature with form body before send API request. for example
initFileUploader(): void {
const self = this;
self.uploader = new FileUploader({
url: 'https://api.cloudinary.com/v1_1/your_cloud_name/upload',
allowedMimeType: ['image/png', 'image/jpg', 'image/jpeg', 'image/gif'],
maxFileSize: 524288,//512 KB
autoUpload: true,
removeAfterUpload: true,
isHTML5: true,
headers: [
{
name: 'X-Requested-With',
value: 'XMLHttpRequest'
}
]
});
self.uploader.onAfterAddingFile = (file) => {
file.withCredentials = false;
};
self.uploader.onSuccessItem = (item, response, status) => {
const resp = <any>JSON.parse(response);
if (resp) {
this.onSuccess.emit(resp);
} else {
this.onError.emit('An error occured during upload. Please retry');
}
};
self.uploader.setOptions(self._uploaderOptions);
self.uploader.onBuildItemForm = (fileItem: any, form: FormData): any => {
let signature = this.generateSignature();
form.append('timestamp', this.unixtime.toString());
form.append('public_id', this.public_id);
form.append('api_key', this.API_KEY); //your cloudinary API_KEY
form.append('signature', signature);
return { fileItem, form };
};
}
I use ng2-file-upload for uploading...
Answered By - Faishal Ahammad
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.