如何使用 python flask 通过 google 应用引擎提供 pdf(或非图像)文件?

How to serve pdf (or non-image) files through google app engine with python flask?

这是我目前用来上传我得到的文件的代码:

header = file.headers['Content-Type']
parsed_header = parse_options_header(header)
blob_key = parsed_header[1]['blob-key']
UserObject(file = blobstore.BlobKey(blob_key)).put()

在服务端,我尝试做与图像相同的事情。也就是说,我得到了 UserObject 然后就做 photoUrl = images.get_serving_url(str(userObject.file)).

令我惊讶的是,这个 hack 在本地服务器上运行得很好。但是,在生产中,它会引发异常:

    File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/images/__init__.py", line 1794, in get_serving_url
    return rpc.get_result()
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/apiproxy_stub_map.py", line 613, in get_result
    return self.__get_result_hook(self)
  File "/base/data/home/runtimes/python27/python27_lib/versions/1/google/appengine/api/images/__init__.py", line 1892, in get_serving_url_hook
    raise _ToImagesError(e, readable_blob_key)
TransformationError

store/serve pdf 等非图像文件的正确方法是什么?

不要使用 images API,它不会工作,因为(至少在生产中)它执行图像 content/format 检查,而您不提供图像。

您可以拥有自己的带有处理程序的请求路径命名空间,就像您应用中的任何其他处理程序一样,可能遵循以下原则:

def pdfServingUrl(request, blob_key):
    from urlparse import urlsplit, urlunsplit
    split = list(urlsplit(request.url))
    split[2] = '/PDF?key=%s' % blob_key.urlsafe() # rewrite the url 'path'
    return urlunsplit(tuple(split))

并且在 /PDF* 的处理程序中:

    blob_key = self.request.get('key')
    self.response.write(blobstore.BlobReader(blob_key).read())

如果你使用the Blobstore API on top of Google Cloud Storage you can also use direct GCS access paths, as mentioned in this answer: https://whosebug.com/a/34023661/4495081.

注意:上面的代码是准系统python建议,仅用于访问 blob 数据。 headers 等其他内容未解决。

根据@NicolaOtasevic 的评论,flask 更完整的代码可能如下所示:

blob_info = blobstore.get(request.args.get('key')) 
response = make_response(blob_info.open().read()) 
response.headers['Content-Type'] = blob_info.content_type 
response.headers['Content-Disposition'] = 'filename="%s"' % blob_info.filename