我将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规则所致),并且不包含图像。互联网的其他方面也不建议像这样存储个人资料图片。
因此,我想做的是制作一个Parse Cloud Code Javascript,通过从URL下载图像并将其作为Parse文件保存在新列中的新数组中,从而将个人资料图片URL迁移为真实图像文件。
这是我想做的:
我希望这是有道理的。我创建了一个Cloud Code函数,如下所示:
Parse.Cloud.define(“ migrateColumn”,函数(请求,响应){
Parse.Cloud.useMasterKey();
var usersToSave = [];
var profileImages = [];
var userQuery = new Parse.Query("User");
userQuery.find().then(function(users) {
for (var a = 0; a < users.length; a++) {
var user = users[a];
var profileURLs = user.get("profilePictures");
for (var b = 0; b < profileURLs.length; b++) {
var url = profileURLs[b];
Parse.Cloud.httpRequest({
url: url
}).then(function(httpResponse) {
var imageBuffer = httpResponse.buffer;
var base64 = imageBuffer.toString("base64");
var file = new Parse.File("userProfileImage.png", { base64: base64 });
profileImages.push(file);
});
}
user.set("profileImages", ["profileImage" + (a + 1)]);
usersToSave.push(user);
}
}).then(function() {
Parse.Object.saveAll(usersToSave, {
success: function() {
response.success("Success : " + profileImages);
}, error: function(error) {
response.error("An error occurred : " + error.message);
}
});
});
});
我了解该操作httpRequest
是异步完成的,因此我需要以Promise
某种方式实现,以等待所有图像完成下载。我对Javascript的了解不足,无法自行构造它。感谢所有帮助。
您走在正确的轨道上。如果您创建执行逻辑任务并返回承诺的函数,一切将变得更加简单。例如,使用单个网址并返回单个PFFile的函数怎么样?
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);
});
注意事项:我没有测试此代码。此处要做的只是重组操作以简化并正确使用Promise。在这些操作中,我使用了您的代码,但也没有进行测试。
我更改的一个设计元素是您似乎要保存一个数组数组profileImages
,例如:[ [ PFFile, '0'], [ PFFile, '1'], ...
我将其更改为仅一个PFFiles数组。我想您希望第二个元素像文件名一样。我在PFFile的构造函数中添加了它所属的名称(该文件的名称并不重要,因为它只会影响该文件的半透明url,无论如何该URL解析都会使它唯一)。
最后的警告。获取大量用户,然后获取大量图像,然后进行大量保存很容易超时。您可能需要在小批用户中运行此程序,以避免超时。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句