1

我使用 Filepicker 从客户的计算机“读取”然后“存储”图像。现在我想使用 Filepicker 调整图像大小,但总是得到 403 错误:

POST https://www.filepicker.io/api/file/w11b6aScR1WRXKFbcXON/convert?_cacheBust=1380818787693 403 (FORBIDDEN) 

我对“读取”、“存储”和“转换”调用使用相同的安全策略和签名。这是错的吗?因为当调用“read”和“store”时,还没有文件句柄(例如 InkBlob.url 中的最后一个字符串部分)。但似乎必须使用“存储”InkBlob 返回的文件句柄生成“转换”策略/签名?如果是这种情况,在javascript中更方便的方法是什么?因为在“转换”中,除非我为此编写 API 调用,否则我无法访问生成安全策略的 Python 函数。

我的代码片段如下(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。

4

3 回答 3

0

所以我终于自己弄清楚了,虽然我后来看到了brettcvz的建议。关键是要“转换”工作,我必须指定上传文件的确切句柄(即从“商店”或“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.");
        }
    });

};
于 2013-10-11T13:46:58.253 回答
0

我的建议是创建两个策略:一个是句柄绑定的并允许存储文件,另一个不是句柄绑定的转换。在这种情况下,您可以设置更短的到期时间来提高安全级别,因为您没有指定句柄。

于 2013-10-09T02:42:38.397 回答
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;
}
于 2013-10-09T09:09:25.457 回答