Javascript 如何使用解析云代码下载图像并将其保存在阵列中?

Javascript 如何使用解析云代码下载图像并将其保存在阵列中?,javascript,parse-platform,cloud,Javascript,Parse Platform,Cloud,我正在使用Parse.com作为iOS应用程序的后端服务,我有一个专栏,将Facebook上的个人资料图片作为URL存储在一个数组中 像这样: [ "https://z-1-scontent.xx.fbcdn.net/hp...e=5737C2D1", "http://files.parsetfss.com/9b0a70...40906b-newProfilePic.png", "http://files.parsetfss.com/9b0a70...24dd6-newP

我正在使用Parse.com作为iOS应用程序的后端服务,我有一个专栏,将Facebook上的个人资料图片作为URL存储在一个数组中

像这样:

[
    "https://z-1-scontent.xx.fbcdn.net/hp...e=5737C2D1",
    "http://files.parsetfss.com/9b0a70...40906b-newProfilePic.png",
    "http://files.parsetfss.com/9b0a70...24dd6-newProfilePic.png"
]
有些时候,这些URL会过期(由于Facebook的规则),并且不包含图像。互联网的其他方面也不建议存储这样的个人资料图片

因此,我想做的是制作一个解析云代码Javascript,通过从URL下载图像并将其保存为解析文件,在新列中的新数组中,将配置文件图片URL迁移到真实的图像文件中

以下是我想做的:

  • 查询解析中的所有用户
  • 获取他们的个人资料图片URL
  • 从每个URL下载图像
  • 创建一个图像文件
  • 将图像添加到新数组中
  • 将该数组保存给用户
我希望这是有道理的。我创建了一个云代码函数,如下所示:

define(“migrateColumn”,函数(请求、响应){

Parse.Cloud.useMasterKey();
var usersToSave=[];
var profileImages=[];
var userQuery=newparse.Query(“用户”);
userQuery.find().then(函数(用户){
对于(var a=0;a
}))


我知道
httpRequest
是异步完成的,我需要以某种方式实现
Promise
,以等待所有图像完成下载。我没有足够的Javascript知识来自己构建这个。非常感谢您的帮助。

您走上了正确的道路。如果您使用能够执行逻辑任务并返回承诺的函数,那么一切都会变得更简单。例如,使用单个url并返回单个文件的函数如何

function fileFromUrl(url, name) {
    return Parse.Cloud.httpRequest({url: url}).then(function(httpResponse) {
        var imageBuffer = httpResponse.buffer;
        var base64 = imageBuffer.toString("base64");
        var file = new Parse.File(name, { base64: base64 });
        // edit - pretty sure file.save resolves to file, but just in case...
        return file.save().then(function() { return file; });
    }, function(error) {
        // can't fetch the image for some reason
        // ideas:
        return null; // and have your UI check for nulls in the user image array
        // or return cannedImage(); where this function returns a promise 
        // for a PFFile that already exists
    });
}
现在更容易为URL数组编写这样的程序

var _ = require('underscore');
function function filesFromUrls(urls) {
    var promises = _.map(urls, function (url, index) {
        return fileFromUrl(url, ''+index);
    });
    return Parse.Promise.when(promises).then(function() {
        return _.toArray(arguments);
    });
}
现在为用户做这件事更容易了

function convertUrlsToFilesForUser(user) {
    var profileURLs = user.get("profilePictures");
    return filesFromUrls(profileURLs).then(function(files) {
        // profileImages should be an array of PFFiles, not an array of arrays as you have it
        user.set("profileImages");
        return user.save();
    });
}
现在在云函数中很容易做到这一点

var userQuery = new Parse.Query("User");
userQuery.find().then(function(users) {
    var promises = _.map(users, function(user) {
        return convertUrlsToFilesForUser(user);
    });
    return return Parse.Promise.when(promises);
}).then(function(result) {
    response.success(result);
}, function(error) {
    response.error(error);
});
注意事项:我没有测试此代码。这里要做的就是重组操作,以简化和正确使用承诺。在这些操作中,我使用了您的代码,而且我也没有对其进行测试

我更改的一个设计元素是,您似乎保存了一个数组数组
profileImages
,例如:
[[PFFile,'0'],[PFFile,'1'],…
我将其更改为PFFiles数组。我想您希望第二个元素类似于文件名。我在PFFile的构造函数中添加了它所属的名称(文件名不重要,因为它只影响文件的半透明url,解析使其具有唯一性)


最后一个警告。获取大量用户,然后获取大量图像,然后进行大量保存可能很容易超时。您可能需要在小批量用户中运行此操作以避免超时。

谢谢danh,这最终会起作用。但我担心的一个问题是:如果URL被破坏(过期)然后
httpResponse
将以
text/plain
的形式返回。这意味着无法创建文件,因此无法保存。那么,有没有办法在响应中检查
httpResponse.status==403
?@ViktorGidlöf,此逻辑中唯一捕获错误的地方是根。如果图像获取导致一个错误,所有的承诺都会落到
响应中
,因此只有处理到该点的用户才能完成。但承诺可以轻松处理上下文中的错误。我制作了一个编辑函数来演示如何处理失败的http请求并继续进行。是的,这很好。我正在考虑创建一个如您所述的函数,名为
CanneImage()
该函数将是一个新的
httpRequest
函数,我将从我知道有图像的URL获取图像?例如,我上传到我自己的服务器上的图像,其中包含占位符图像。我会在错误函数中执行此操作,还是如何创建占位符?谢谢!有几个选项,但我预先fer将其保留为空。在大多数情况下,替换一个固定的图像是UI的业务,它应该使用一个单独的架构,针对静态内容进行优化,以获得类似的内容。如果有充分的理由在云中这样做,那么在将其句柄保留在一个新类中后,获取该文件并构建PFFile。重新创建PFFile将是非常浪费的-每次需要图像时,获取并创建一个新的PFFile。是的,我找到了它,并通过返回一个
占位符文件()来工作
错误句柄中的函数,该函数反过来从未被破坏的URL返回占位符图像。现在我关心的另一个问题是,我想从下载的文件中生成一个缩略图图像,并将其设置为另一列。但这可能是另一个问题?
var userQuery = new Parse.Query("User");
userQuery.find().then(function(users) {
    var promises = _.map(users, function(user) {
        return convertUrlsToFilesForUser(user);
    });
    return return Parse.Promise.when(promises);
}).then(function(result) {
    response.success(result);
}, function(error) {
    response.error(error);
});