use*_*503 8 upload google-app-engine callback blobstore google-cloud-storage
当使用BlobStore的createUploadURL函数上传到GCS(Google云端存储)时,我可以提供回调以及将被发布到回调URL的标题数据.
使用GCS的签名URL似乎没有办法做到这一点
我知道有对象更改通知但不允许用户在POST的标题中提供上传特定信息,这可以通过createUploadURL的回调来实现.
我的感觉是,如果createUploadURL能做到这一点,必须有办法用标识的URL的做到这一点,但我找不到它的任何文件.我想知道是否有人可能知道createUploadURL如何实现该回调调用行为.
PS:我正在尝试离开createUploadURL因为__BlobInfo__它创建的实体,这对于我不需要的特定用例,并且似乎是不可磨灭的并且浪费存储空间.
更新:它工作了!方法如下:
答案很长:
如果你看看签署-URL页面,在HTTP_Verb面前,在说明,有一个微妙的注意,该页面只是相关的GET,HEAD,PUT和DELETE,但POST是一个完全不同的游戏.我错过了这个,但事实证明这非常重要.
有一整页HTTP标头没有列出可以与POST一起使用的重要标头; 该标题是success_action_redirect,正如voscausa正确回答的那样.
在POST页面中,Google"强烈建议"使用PUT,除非处理表单数据.但是,POST有一些很好的功能,PUT没有.他们可能会担心POST给我们带来了太多的字符串.
但我要说完全值得删除createUploadURL,并编写自己的代码来重定向到回调.方法如下:
码:
如果您正在使用Python voscausa的代码非常有帮助.
我正在使用apejs在Java应用程序中编写javascript,所以我的代码如下所示:
var exp = new Date()
exp.setTime(exp.getTime() + 1000 * 60 * 100); //100 minutes
json['GoogleAccessId'] = String(appIdentity.getServiceAccountName())
json['key'] = keyGenerator()
json['bucket'] = bucket
json['Expires'] = exp.toISOString();
json['success_action_redirect'] = "https://" + request.getServerName() + "/test2/";
json['uri'] = 'https://' + bucket + '.storage.googleapis.com/';
var policy = {'expiration': json.Expires
, 'conditions': [
["starts-with", "$key", json.key],
{'Expires': json.Expires},
{'bucket': json.bucket},
{"success_action_redirect": json.success_action_redirect}
]
};
var plain = StringToBytes(JSON.stringify(policy))
json['policy'] = String(Base64.encodeBase64String(plain))
var result = appIdentity.signForApp(Base64.encodeBase64(plain, false));
json['signature'] = String(Base64.encodeBase64String(result.getSignature()))
Run Code Online (Sandbox Code Playgroud)
上面的代码首先提供相关字段.然后创建一个策略对象.然后它将字符串化为对象并将其转换为字节数组(您可以在Java中使用.getBytes.我必须为javascript编写一个函数).此数组的base64编码版本填充策略字段.然后使用appidentity包签名.最后签名是base64编码的,我们完成了.
在客户端,json对象的所有成员将被添加到表单中,除了作为表单地址的uri.
var formData = new FormData(document.forms.namedItem('upload'));
var blob = new Blob([thedata], {type: 'application/json'})
var keys = ['GoogleAccessId', 'key', 'bucket', 'Expires', 'success_action_redirect', 'policy', 'signature']
for(field in keys)
formData.append(keys[field], url[keys[field]])
formData.append('file', blob)
var rest = new XMLHttpRequest();
rest.open('POST', url.uri)
rest.onload = callback_function
rest.send(formData)
Run Code Online (Sandbox Code Playgroud)
如果您未提供重定向,则响应状态将为204以获得成功.但是如果你做重定向,状态将是200.如果你得到403或400有关签名或政策可能是错误的.看看responseText.如果经常有帮助.
有几点需要注意:
createUploadURL有什么问题?
上面的方法是手动createUploadURL.但:
__BlobInfo__创建许多索引并且不可磨灭的对象.这让我感到恼火,因为它浪费了很多空间(这让我想起了一个单独的问题:问题4231.请给它一个明星)对于极少数的javascript应用程序工程师:
function StringToBytes(sz) {
map = function(x) {return x.charCodeAt(0)}
return sz.split('').map(map)
}
Run Code Online (Sandbox Code Playgroud)
当您使用 GCS post 对象时,您可以在策略文档中包含 succes_action_redirect。
此处的文档: 文档: https: //cloud.google.com/storage/docs/xml-api/post-object
Python 示例此处: https: //github.com/voscausa/appengine-gcs-upload
回调结果示例:
def ok(self):
""" GCS upload success callback """
logging.debug('GCS upload result : %s' % self.request.query_string)
bucket = self.request.get('bucket', default_value='')
key = self.request.get('key', default_value='')
key_parts = key.rsplit('/', 1)
folder = key_parts[0] if len(key_parts) > 1 else None
Run Code Online (Sandbox Code Playgroud)