用Blobstore在GAE上存储二进制文件

标签:Google App Engine, Python

GAE SDK 1.3.0版发布带来了一个好消息,可以用Blobstore来存储大型二进制文件了,上限为单个文件50MB。
不过该服务还是实验性质,API可能会更改,而且必须开启支付(本地测试是免费的)。
目前Blobstore的免费存储配额为1GB,而带宽是和其他请求一样计算的;只要不超过配额,就无需多付费。
下面照惯例,仍只介绍Python版的,这里是官方文档

首先必须指出,和Datastore不一样的是,应用程序并不能直接访问Blobstore里的文件。
在上传时,应用程序调用Datastore API来生成一个URL,让用户直接通过HTTP POST方法来上传(一般为一个包含文件类型的表单);之后应用程序可以这个blob(二进制文件)的key。
而输出时,在header中进行指定,App Engine就会自动用blob来替换输出内容了。
Blob由API进行创建,不能被更改,但可以被删除。每个blob都有对应的描述信息记录(BlobInfo)在datastore里。查询时可以使用blob的key或其他属性。

接下来就说下如何上传。
先调用blobstore.create_upload_url()函数,参数为上传后重定向到的网址,返回一个上传地址:
upload_url = blobstore.create_upload_url('/upload')
接着输出一个表单,action为刚才生成的上传网址,注意设置enctype="multipart/form-data"
    self.response.out.write('<html><body>')
    self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
    self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit" 
        name="submit" value="Submit"> </form></body></html>""")
上传完成后,用户会被重定向到你设置的网址(/upload),用一个handler来处理这个网址,即可得知上传的文件信息。如果使用webapp框架的话,可以用blobstore_handlers.BlobstoreUploadHandler来处理:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
    def post(self):
        upload_files = self.get_uploads('file')  # 'file'是表单中上传的文件的name字段
        blob_info = upload_files[0] # 注意name是可以重复的,所以是一个列表;这里只取第0个即可
        self.redirect('/serve/%s' % blob_info.key()) # 重定向到下载页面(必须进行重定向,即状态码为301、302或303)
这样上传就完成了,接下来看下载。
如果使用webapp框架的话,可以用blobstore_handlers.BlobstoreDownloadHandler来处理:
class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, blob_key): # blob_key是编码后的参数
        blob_key = str(urllib.unquote(blob_key))
        blob_info = blobstore.BlobInfo.get(blob_key)
        self.send_blob(blob_info)

上传下载说完了,再介绍下BlobInfo类。
这个类用于存储blob的描述信息,它看上去很像Model类,因此也可以用相似的API来查询。此外还有几个实例属性:content_type(MIME类型)、creation(创建时间)、filename(文件名)和size(字节大小)。
和其他实体不一样的是,BlobInfo实体是不能被修改的,而且调用delete方法时会自动删除对应的Blobstore对象。
此外,使用parse_blob_info()函数可以直接生成一个BlobInfo对象,而无需访问数据库。

BlobKey这个类的对象则用于存储Blobstore对象的键值。
在上传时,X-AppEngine-BlobKey这个header字段会被填入字符串类型的key,再传入BlobKey()构造函数即可创建BlobKey对象。不过使用blobstore_handlers.BlobstoreUploadHandler就无需自己处理了。
创建BlobInfo实体的引用时,可以使用BlobReferenceProperty类型,它也是一个BlobKey对象。
在搜索一个BlobInfo实体时,可将BlobKey对象传给BlobInfo.get(),来找到对应的实体。

顺带一提,如果要hook这个服务的话,它的服务名是blobstore,更多信息可以自己研究下源代码。

其他就没什么好说的了,文档里有完整的示例代码,大家可以去试试。

4条评论 你不来一发么↓ 顺序排列 倒序排列

    向下滚动可载入更多评论,或者点这里禁止自动加载

    想说点什么呢?