如何使用App Engine SDK 提供云存储文件
在应用引擎中,我可以使用我应用的默认存储桶来提供像PDF这样的云存储文件:
http://storage.googleapis.com/<appid>.appspot.com/<file_name>
但是,我该如何在SDK中提供本地的云存储文件,而不使用blob_key呢?
我这样写入默认存储桶:
gcs_file_name = '/%s/%s' % (app_identity.get_default_gcs_bucket_name(), file_name)
with gcs.open(gcs_file_name, 'w') as f:
f.write(data)
在SDK中,默认存储桶的名称是'app_default_bucket'
在SDK的数据存储中,我有一个类型为GsFileInfo的记录,显示:文件名:/app_default_bucket/example.pdf
更新和解决方法:你可以为非图像文件(比如css、js和pdf)获取一个服务网址。
gs_file = '/gs/%s/%s/%s' % (app_identity.get_default_gcs_bucket_name(), folder, filename)
serving_url = images.get_serving_url(blobstore.create_gs_key(gs_file))
3 个回答
我之前在这里寻找答案,现在我想分享一下我找到的解决办法,因为我已经搞定了。
现在你可以做到这一点,虽然过程有点麻烦。欺骗图像或blob存储的API不再被支持,而且似乎也不再有效。
你可以参考以下链接:
- https://cloud.google.com/storage/docs/access-control/signed-urls
- https://cloud.google.com/storage/docs/access-control/create-signed-urls-gsutil
如果你给你的链接签名,就可以生成自动过期的链接,供匿名用户或付费用户使用。你可能不想用这种方式提供整个网站的内容,但对于PDF文件或其他类似的东西,这是一种有效且相对安全的选择。
文档中缺少的一点是,你可能需要去掉规范扩展头中的换行符。当签名不正确时,存储端点会告诉你它期望什么。
另外,你的主机应该是:https://storage-download.googleapis.com/
如果你使用的是App Engine,那么GoogleAccessId
是:<项目名称>@appspot.gserviceaccount.com
可以查看:app_identity.get_service_account_name()
生成签名的示例:
from google.appengine.api import app_identity
def signFile(path, verb='GET', md5='', contentType='',
expiration=''):
signatureRequest = '{}\n{}\n{}\n{}\n{}'.format(
verb, md5, contentType, expiration, path)
return app_identity.sign_blob(signatureRequest)
这会返回一个包含(privateKey, binarySignature)
的元组。
现在你需要构建URL。签名应该先进行base64编码,然后再进行URL编码。接下来可以参考以下内容来完成URL的构建。你可能应该使用上面提到的下载主机。
文档中的示例URL:
https://storage.googleapis. com/example-bucket/cat.jpeg?GoogleAccessId=example@example-project.iam.gservicea ccount.com&Expires=1458238630&Signature=VVUgfqviDCov%2B%2BKnmVOkwBR2olSbId51kSib uQeiH8ucGFyOfAVbH5J%2B5V0gDYIioO2dDGH9Fsj6YdwxWv65HE71VEOEsVPuS8CVb%2BVeeIzmEe8z 7X7o1d%2BcWbPEo4exILQbj3ROM3T2OrkNBU9sbHq0mLbDMhiiQZ3xCaiCQdsrMEdYVvAFggPuPq%2FE QyQZmyJK3ty%2Bmr7kAFW16I9pD11jfBSD1XXjKTJzgd%2FMGSde4Va4J1RtHoX7r5i7YR7Mvf%2Fb17 zlAuGlzVUf%2FzmhLPqtfKinVrcqdlmamMcmLoW8eLG%2B1yYW%2F7tlS2hvqSfCW8eMUUjiHiSWgZLE VIG4Lw%3D%3D
希望这能帮助到某个人!
哦,对了,只有当你的存储桶不是公开可访问(可读所有)时,你才需要做所有的签名相关工作。
这是你在开发模式下从 app_identity_stub.py 文件中看到的值:
APP_DEFAULT_GCS_BUCKET_NAME = 'app_default_bucket'
这个文件里的注释解释得很清楚:
这个服务的行为和生产环境中的服务一样,只是使用的是固定的值,而不是特定于应用的值。
在你的生产代码中,你应该能得到正确的 URL。
编辑:
这是来自支持论坛的内容:
在开发模式下,应用引擎工具会在本地模拟 Google Cloud Storage 服务。在这个模拟环境中,存储的对象是临时的,所以你的应用会失败,因为你想要的对象在本地存储中不存在。如果你先创建(并可选择性地写入)你想要读取的对象,它在开发模式下应该能正常工作(我试过是可以的)。当然,在生产服务中,存储的对象是持久的,所以在生产模式下运行应用时就不需要这个额外的步骤(假设对象已经存在)。
希望这能帮到你,
Marc Google Cloud Storage 团队
这意味着你必须先写一个文件,然后才能使用它。如果我理解得没错,你可以使用任何桶的名字来实现这个目的,包括 'app_default_bucket'。
更新:我发现了一个功能,可以通过SDK来服务云存储文件:
http://localhost:8080/_ah/gcs/app_default_bucket/filename
这意味着我们不需要图片的服务网址来提供非图片文件,如下所示!!!
为了为默认存储桶中的云存储文件(比如图片、CSS、JS和PDF)创建一个服务网址,我使用了这段代码进行测试(SDK)和GAE生产环境:
重要提示:images.get_serving_url()在SDK中也可以用于非图片文件!!
在SDK中,你仍然需要使用blobstore来读取一个blob,并为云存储对象创建一个服务网址。
我还添加了在SDK和GAE生产环境中读取、写入和上传云存储blob的代码。
代码可以在这里找到。