如何在保存到 Parse.Cloud.beforeSave 之前将照片调整为多种照片尺寸

Jay*_*son 3 parse-platform

首先让我先说我让这段代码完美地工作以获得缩略图(https://parse.com/docs/cloud_modules_guide#images

我当前的代码是:

var Image = require("parse-image");

var photoSizesArray = {};
photoSizesArray["Thumb"] = [40,40];
photoSizesArray["Normal"] = [180,180];

    Parse.Cloud.beforeSave("_User", function(request, response) {
      var user = request.object;
      if (!user.get("profilePicture")) {
        // response.error("Users must have a profile photo.");
        // return;
        response.success();
        return;
      } else {


        if (!user.dirty("profilePicture")) {
          // The profile photo isn't being modified.
          response.success();
          return;
        }

        for (var key in photoSizesArray) {

          Parse.Cloud.httpRequest({
            url: user.get("profilePicture").url()

          }).then(function(response) {
            var image = new Image();
            return image.setData(response.buffer);

          }).then(function(image) {
            // Crop the image to the smaller of width or height.
            var size = Math.min(image.width(), image.height());
            return image.crop({
              left: (image.width() - size) / 2,
              top: (image.height() - size) / 2,
              width: size,
              height: size
            });

          }).then(function(image) {

              // Resize the image to 40 x 40.
              return image.scale({
                width: photoSizesArray[key][0],
                height: photoSizesArray[key][1]
              });


          }).then(function(image) {
            // Make sure it's a JPEG to save disk space and bandwidth.
            return image.setFormat("JPEG");

          }).then(function(image) {
            // Get the image data in a Buffer.
            return image.data();

          }).then(function(buffer) {
            // Save the image into a new file.
            var base64 = buffer.toString("base64");
            var cropped = new Parse.File("profilePicture"+key+"_" + Parse.User.current().id + ".jpg", { base64: base64 });
            return cropped.save();

          }).then(function(cropped) {
            // Attach the image file to the original object.
            user.set("profilePicture" + key, cropped);

          }).then(function(result) {
            response.success();
          }, function(error) {
            response.error(error);
          });

      }
    }
  });
Run Code Online (Sandbox Code Playgroud)

我的问题是如何在同一个 _User 表中保存相同的照片但大小不同?

目前我收到一条错误消息

“无法多次调用多个成功/错误”

或者有时,如果它确实有效,它只会保存两种照片尺寸中的一种。

任何关于我应该如何移动成功/错误响应的帮助将不胜感激。

或者我是否应该研究一种不同的方法来保存额外的照片尺寸。

谢谢,

Jay*_*son 5

因此,经过大量的研究和反复试验,我终于明白了 Promise 如何与 httpRequests 一起工作。

我最初在让 2 个同时的 httpRequests 彼此并行时遇到问题,因为出于某种原因,它被覆盖或只是被忽略。

这是您需要了解的内容。

  1. Parse.Cloud.httpRequest 返回一个 Parse.Promise 对象。

  2. 实际上,您必须在 for 循环中返回对象。这意味着我将 Parse.Cloud.httpRequest 对象放置在 for 循环之外的单独函数中,我可以在 for 循环内调用该函数。

  3. 当您最终将所有 Promise 对象收集到一个 Promise 数组中时,您可以使用 Parse.Promise.when(promises).then()... 来遍历它。

以下是我的代码,它获取上传的照片,处理 2 种尺寸并将它们保存在单独的 _User 列中 - profilePictureThumb 和 profilePictureNormal。

var Image = require("parse-image");
Parse.Cloud.beforeSave("_User", function(request, response) {
var user = request.object;
if (!user.get("profilePicture")) {
  // response.error("Users must have a profile photo.");
  // return;
  response.success();
  return;
} else {

    if (!user.dirty("profilePicture")) {
      // The profile photo isn't being modified.
      response.success();
      return;
    }    

    var promises = [];
    var sizes = { 
        Normal: { width: 180, height: 180 }, 
        Thumb: { width: 80, height: 80 }
    };

    for(var key in sizes) {            
        promises.push(
            ProcessUrls(user.get("profilePicture").url(), key, sizes[key])
        );
    }

    return Parse.Promise
        .when(promises)
        .then(function () {
            // results are passed as function arguments
            // map processed photos to result
            var photos = Array.prototype.slice.call(arguments);
            var result = {};
            console.log("promises:" + promises)

            photos.forEach(function (photo) {
                console.log("photo.key: " + photo.key)
                result[photo.key] = photo;

                user.set('profilePicture' + photo.key, photo.file);

            });
            response.success();
        }, function(error) {
            response.error("error: " + error);
    });

} // Else



});

function ProcessUrls(fullUrl, key, size) {
/* debugging
console.log("fullUrl: " + fullUrl);
console.log("key: " + key);
console.log("width: " + size["width"]);
console.log("height: " + size["height"]);
*/    
return Parse.Cloud.httpRequest({ url: fullUrl })
.then(function(response) {
    var image = new Image();
    return image.setData(response.buffer);

})
.then(function(image) {
    // Crop the image to the smaller of width or height.
    var size = Math.min(image.width(), image.height());
    return image.crop({
      left: (image.width() - size) / 2,
      top: (image.height() - size) / 2,
      width: size["width"],
      height: size["height"]
    })
})
.then(function(image) {
    // Resize the image to 40 x 40.
    return image.scale({
        width: size["width"],
        height: size["height"]
    });
})
.then(function(image) {
    // Make sure it's a JPEG to save disk space and bandwidth.
    return image.setFormat("JPEG");
})
.then(function(image) {
    // Get the image data in a Buffer.
   return image.data();
}).then(function(buffer) {
    // Save the image into a new file.
    var base64 = buffer.toString("base64");
    var cropped = new Parse.File("profilePicture"+key+"_" + Parse.User.current().id + ".jpg", { base64: base64 });
    return cropped.save()
    .then(function (file) {
         // this object is passed to promise below
         return { 
             key: key, 
             file: file
         };
    })
})
};
Run Code Online (Sandbox Code Playgroud)

感谢 @Andy 和一大堆其他 StachOverflow 用户,我把这段代码拼凑在一起。