我使用Filepicker“读取”然后从客户的计算机“存储”图像。现在我想使用Filepicker调整图像大小但总是得到403错误:
POST https://www.filepicker.io/api/file/w11b6aScR1WRXKFbcXON/convert?_cacheBust=1380818787693 403 (FORBIDDEN)
我对“读取”,“存储”和“转换”调用使用相同的安全策略和签名。这是错的吗?因为当调用“read”和“store”时,还没有文件句柄(例如InkBlob.url中的最后一个字符串部分)。但似乎必须使用“store”InkBlob返回的文件句柄生成“转换”策略/签名?如果是这种情况,在javascript中更方便的做法是什么?因为在“转换”中我无法访问生成安全策略的Python函数,除非我为此编写API调用。
我的代码片段如下(initialFpSecurityObj是使用空句柄在Python中预生成的):
filepicker.store(thumbFile, {
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
location: "S3",
path: 'thumbs/' + initialFpSecurityObj.uniqueName + '/',
},function(InkBlob){
console.log("Store successful:", JSON.stringify(InkBlob));
processThumb(InkBlob);
}, function(FPError){
console.error(FPError.toString());
});
var processThumb = function(InkBlob){
filepicker.convert(InkBlob, {
width: 800,
height: 600,
format: "jpg",
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
}, function(InkBlob){
console.log("thumbnail converted and stored at:", InkBlob);
}, function(FPError){
console.error(FPError);
};
}
非常感谢你的帮助。
---编辑---
以下是生成initialFpSecurityObj
的Python代码的代码段def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
expiry = int(time() + policyLife)
json_policy = json.dumps({'handle': handle, 'expiry': expiry})
policy = base64.urlsafe_b64encode(json_policy)
secret = 'XXXXXXXXXXXXXX'
signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()
uniqueName = hashlib.md5()
uniqueName.update(signature + repr(time()))
uniqueName = uniqueName.hexdigest() + str(userId)
return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}
fp_security_options = generateFpSecurityOptions(None, request.user.id)
然后在django模板中检索fp_security_options:
var initialFpSecurityObj = {{fp_security_options|as_json|safe}};
生成fp_security_options的方式对我(前同事的代码)是可疑的,因为句柄是None。
答案 0 :(得分:0)
我的建议是创建两个策略:一个是句柄绑定的,允许存储文件,另一个不是转换的句柄绑定。在这种情况下,您可以设置较短的到期时间以提高安全级别,前提是您没有指定句柄。
答案 1 :(得分:0)
您的问题可能是您的政策不包含任何“通话”规范。我建议:
json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':['pick','store','read','convert']})
但正如我们(非常忙碌;)brettcvz建议的那样,仅限转换,这已经足够了:
json_policy = json.dumps({'handle': handle, 'expiry': expiry, 'call':'convert'})
您可以在安全文档https://developers.inkfilepicker.com/docs/security/
中找到如果您仍有问题,请使用REST呼叫,它是免费的。以下方法是JavaScript并将URL返回到filepicker的REST端点,该端点可用于检索转换后的图像。 _options对象看起来像这样
var myOptions = {
w: 150,
h: 150,
fit: "crop",
align: "faces",
format: "jpg",
quality: 86
};
并将使用文件选择器REST-API指定的所有参数(请查看https://developers.inkfilepicker.com/docs/web/#inkblob-images)。
function getConvertedURL(_handle, _options, _policy, _signature) {
// basic url piece
var url = "https://www.filepicker.io/api/file/" + _handle + "/convert?";
// appending options
for (var option in _options) {
if (_options.hasOwnProperty(option)) {
url += option + "=" + _options[option] + "&";
}
}
// appending signed policy
url += "signature=" + _signature + "&policy=" + _policy;
return url;
}
答案 2 :(得分:0)
所以我终于弄明白了,虽然我之后看到了brettcvz的建议。关键是'转换'工作,我必须指定上传文件的确切句柄(即从'store'或'pickAndStore'调用返回的InkBlob的url属性中字符串的最后一位。
我做的第一件事就是编辑生成安全策略和签名的Python函数:
def generateFpSecurityOptions(handle, userId, policyLife=DEFAULT_POLICY_LIFE):
expiry = int(time() + policyLife)
json_policy = json.dumps({'handle': handle, 'expiry': expiry})
policy = base64.urlsafe_b64encode(json_policy)
secret = 'XXXXXXXXXXXXXX'
signature = hmac.new(secret, policy, hashlib.sha256).hexdigest()
if not handle == None:
uniqueName = handle
else:
uniqueName = hashlib.md5()
uniqueName.update(signature + repr(time()))
uniqueName = uniqueName.hexdigest() + str(userId)
return {'policy':policy, 'signature':signature, 'expiry':expiry, 'uniqueName':uniqueName}
fp_security_options = generateFpSecurityOptions(None, request.user.id)
然后我必须在我们的Django框架中建立API调用,以通过AJAX动态获取此安全策略对象。我很幸运,我的同事以前写过它。所以我只是在Javascript中调用API函数来检索特定于文件的安全策略对象:
var initialFpSecurityObj = {{fp_security_options|as_json|safe}};
filepicker.store(thumbFile, {
policy: initialFpSecurityObj.policy,
signature: initialFpSecurityObj.signature,
access: "public"
}, function(InkBlob) {
processThumb(InkBlob);
}, function(FPError) {
console.error(FPError.toString());
}, function(progress) {
console.log("Loading: " + progress + "%");
});
var processThumb = function(InkBlob) {
var fpHandle = InkBlob.url.split('/').pop();
$.ajax({
url: API_BASE + 'file_picker_policy',
type: 'GET',
data: {
'filename': fpHandle
},
dataType: 'json',
success: function(data) {
var newFpSecurityObj = data.data;
filepicker.convert(InkBlob, {
width: 800,
height: 600,
format: "jpg",
policy: newFpSecurityObj.policy,
signature: newFpSecurityObj.signature,
}, {
location: "S3",
path: THUMB_FOLDER + '/' + newFpSecurityObj.uniqueName + '/',
}, function(fp) { // onSuccess
console.log("successfully converted and stored!");
// do what you want with the converted file
}, function(FPError) { // onError
console.error(FPError);
});
},
failure: function() {
alert("There was an error converting the thumbnail! Please try again.");
}
});
};