如何在下载期间将Google App Engine发送到gunzip?

时间:2014-11-12 17:50:04

标签: python google-app-engine blobstore

我正在尝试让Google App Engine通过设置响应标头自动对我的.gz blob文件(单个文件压缩)进行枪口扫描,如下所示:

class download(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        self.response.headers['Content-Encoding'] = str('gzip')
        # self.response.headers['Content-type'] = str('application/x-gzip')
        self.response.headers['Content-type'] = str(blob_info.content_type)
        self.response.headers['Content-Length'] = str(blob_info.size)
        cd = 'attachment; filename=%s' % (blob_info.filename)
        self.response.headers['Content-Disposition'] = str(cd)
        self.response.headers['Cache-Control'] = str('must-revalidate, post-check=0, pre-check=0')
        self.response.headers['Pragma'] = str(' public')
        self.send_blob(blob_info)

运行此命令时,将下载不带.gz扩展名的文件。但是,下载的文件仍然是gzip压缩。下载数据的文件大小与服务器上的.gz文件大小相匹配。此外,我可以通过手动解压缩下载的文件来确认这一点。我试图避免手动喷枪步骤。

我试图让blob文件在下载过程中自动gunzip。我做错了什么?

顺便说一句,gzip文件只包含一个文件。在我的自托管(非Google)服务器上,我可以通过设置相同的响应标头来完成自动gunzip;虽然我的代码是用PHP编写的。

更新:

我重写了处理程序以从桶中提供数据。但是,这会生成HTML 500错误。在失败之前部分下载文件。重写如下:

class download(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        resource = str(urllib.unquote(resource))
        blob_info = blobstore.BlobInfo.get(resource)
        file = '/gs/mydatabucket/%s' % blob_info.filename
        print file
        self.response.headers['Content-Encoding'] = str('gzip')
        self.response.headers['Content-Type'] = str('application/x-gzip')
        # self.response.headers['Content-Length'] = str(blob_info.size)
        cd = 'filename=%s' % (file)
        self.response.headers['Content-Disposition'] = str(cd)
        self.response.headers['Cache-Control'] = str('must-revalidate, post-check=0, pre-check=0')
        self.response.headers['Pragma'] = str(' public')
        self.send_blob(file)

在服务器终止之前,将6,094,848字节文件的540,672字节下载到客户端并发出500错误。当我发出' file'在来自命令行的部分下载文件中,Mac OS似乎正确地将文件格式标识为' SQLite 3.x数据库'文件。知道服务器上500错误的原因吗?我该如何解决这个问题?

2 个答案:

答案 0 :(得分:3)

您应首先检查您的请求客户端是否支持gzip压缩内容。如果它支持gzip内容编码,那么您可以使用正确的content-encodingcontent-type标头传递gzip压缩包,否则您需要为客户端解压缩blob。您还应验证您的blob content_type不是gzip(这取决于您开始创建blob的方式!)

您可能还想查看Google云端存储,因为只要您在使用正确的内容编码和内容类型元数据存储数据之前正确压缩数据,它就会自动处理gzip传输。

请参阅此问题:Google cloud storage console Content-Encoding to gzip

或GCS文档:https://cloud.google.com/storage/docs/gsutil/addlhelp/WorkingWithObjectMetadata#content-encoding

在AppEngine中使用blobstore时,您可以轻松地使用GCS(如果不是更容易),它似乎是未来使用的首选存储层。我这样说是因为文件API已被弃用,这使得blobstore交互更容易,并且已经对GCS库做出了很大的努力和进步,使得API类似于基本的python文件交互API

<强>更新

由于对象存储在GCS中,因此您可以使用302重定向将用户指向文件,而不是依赖Blobstore API。这消除了Blobstore API和GAE的任何未知行为,使用您打算使用的内容类型和内容编码来提供存储的对象。对于具有公共读取ACL的对象,您可以直接将它们指向storage.googleapis.com/<bucket>/<object><bucket>.storage.googleapis.com/<object>。或者,如果您希望应用程序逻辑指示访问权限,则应将ACL保持为私有对象,并且可以使用GCS Signed URLs创建在执行302重定向时使用的短期URL。

值得注意的是,如果您希望用户能够通过GAE上传对象,您仍然可以使用Blobstore API来处理在GCS中存储文件,但是您必须在之后修改对象它被上传以确保使用正确的gzip压缩和内容编码元数据。

class legacy_download(blobstore_handlers.BlobstoreDownloadHandler):
    def get(self, resource):
        filename = str(urllib.unquote(resource))
        url = 'https://storage.googleapis.com/mybucket/' + filename
        self.redirect(url)

答案 1 :(得分:0)

如果客户支持,GAE已经使用gzip提供所有服务。 所以我认为更新后发生的事情是浏览器希望有更多的文件,但GAE认为它已经在文件的末尾,因为它已经被gzip压缩了。这就是你获得500的原因。 (如果这是有道理的)

无论如何,由于GAE已经为您处理压缩,最简单的方法可能是将非压缩文件放在GCS中,让Google基础架构在您提供服务时自动为您处理压缩。