在下载过程中如何让googleappengine运行到gunzip?

2024-04-19 20:11:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试通过将响应头设置为如下所示,使Google App Engine自动gunzip我的.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编写的。在

更新:

我重写了处理程序以提供来自bucket的数据。但是,这会产生HTML500错误。文件在失败前已部分下载。重写如下:

^{pr2}$

这将在服务器终止并发出500错误之前将6094848字节文件的540672字节下载到客户端。当我从命令行对部分下载的文件发出“file”时,macos似乎正确地将文件格式标识为“SQLite 3.x database”文件。你知道为什么服务器上出现500错误吗?我怎样才能解决这个问题?在


Tags: 文件selfinfo服务器responsetype错误content
2条回答

您应该首先检查请求的客户机是否支持gzip内容。如果它确实支持gzip内容编码,那么您可以通过正确的content-encoding和{}头来传递gzip压缩的blob,否则需要为客户端解压缩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重定向将用户指向文件,而不是依赖blobstoreapi。这就消除了blobstoreapi和GAE使用您想要使用的内容类型和内容编码来传递存储对象的任何未知行为。对于具有公共读取ACL的对象,您可以直接将它们指向storage.googleapis.com/<bucket>/<object>或{}。或者,如果您想让应用程序逻辑指定访问权限,您应该将对象的ACL保持为私有,并且可以使用GCS Signed URLs创建短生命的url,以便在执行302重定向时使用。在

值得注意的是,如果您希望用户能够通过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)

如果客户机支持的话,GAE已经使用gzip提供了所有服务。 所以我认为在你的更新之后,浏览器希望有更多的文件,但是GAE认为它已经在文件的末尾了,因为它已经被gzip压缩了。这就是为什么你能拿到500。 (如果有道理的话)

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

相关问题 更多 >