toddg
toddg

Reputation: 2906

Parse Resize Image not Saving Properly

I am trying to resize an image in Parse Cloud Code following the Cloud Modules Guide.

The basic idea is as follows: when afterSave is called on a User, check if the small profile pic is null and standard profile pic is not null. If true, get the standard profile pic from Parse, read into buffer, create file, save file, then add file to User and Save. Unfortunately, the file doesn't seem to be saving properly.

Here is the cloud afterSave function:

    Parse.Cloud.afterSave(Parse.User, function(request) {

    ...

        Parse.Cloud.httpRequest({
        url: request.object.get("profilePicture").url(),
        success: function(response) {
            // The file contents are in response.buffer.

            var image = new Image();
            console.log("Buffer: " + response.buffer );
            console.log("Length " + response.buffer.length);
            image.setData(response.buffer);
            var imgData = image.data();


            // Save the image into a new file.
            var base64 = imgData.toString("base64");
            var scaled = new Parse.File("thumbnail.png", { base64: base64 });
            scaled.save().then(function() {
                request.object.set("profilePictureSmall", scaled);
                request.object.save();
            }, function(error) {
                console.log( "The file either could not be read, or could not be saved to Parse.");
            });
        }
    });
    ...
});

The User object seems to save fine, but the image file that is saved is a broken image.

The strange thing is that console.log("Length " + response.buffer.length); outputs the proper size to the console.

console.log("Buffer: " + response.buffer ); Gives output: �PNG

Any idea what's going on here?

Upvotes: 0

Views: 1374

Answers (1)

Timothy Walters
Timothy Walters

Reputation: 16874

The issue is that setData() is an async call, you need to wait for it to finish before you do the next bit.

http://parse.com/docs/js/symbols/Image.html#setData

Here's a snippet:

Parse.Cloud.httpRequest({
    url: request.object.get("profilePicture").url()
}).then(function(response) {
    var image = new Image();
    return image.setData(response.buffer);
}).then(function(image) {
    // make it fit in 100x100
    var width = 100, height = 100;
    if (image.width() > image.height()) {
        // work out scaled height
        height = image.height() * (100/image.width());
    } else {
        // work out scaled width
        width = image.width() * (100/image.height());
    }
    console.log("..scale to " + width + "x" + height);
    return image.scale({
        width: width,
        height: height
    });
}).then(function(scaledImage) {
    // get the image data in a Buffer
    return scaledImage.data();
}).then(function(buffer) {
    // save the image to a new file
    console.log("..saving file");
    var base64 = buffer.toString("base64");
    var name = "Thumbnail.png";
    var thumbnail = new Parse.File(name, { base64: base64 });
    return thumbnail.save();
}).then(function(thumbnail) {
    // attach the image file to the original object
    console.log("..attaching file");
    request.object.set("profilePictureSmall", thumbnail);
    return request.object.save();
}) /* further chaining here for after-save */;

You basically have to chain your promises together to allow the previous step to finish.

Upvotes: 4

Related Questions