我在Python中使用Google App Engine来处理小型网络应用程序。
我有一些文件存储在我的GCS中,只有在用户登录时才能提供。
我虽然这很容易,但是我确实因为我的代码而错过了一步:
import cloudstorage as gcs
class Handler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
class testHandler (Handler):
def get (self):
bucket = '/my_bucket'
filename = '/pdf/somedoc.pdf'
user = users.get_current_user()
if user:
pdf = gcs.open(bucket+filename)
self.write(pdf)
只给出:
<cloudstorage.storage_api.ReadBuffer object at 0xfbb931d0>
我需要的是文件本身。
任何人都可以告诉我,我错过了哪一步?
由于
答案 0 :(得分:1)
首先我写的是文件的地址,而不是文件。
所以正确的电话会是:
self.write(pdf.read())
另外,我必须将'Content-Type'标题更改为'application / pdf',以允许浏览器提供文件而不是文本文件。
无论如何,结果是:
class pHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.headers['Content-Type']='application/pdf'
self.response.out.write(*a, **kw)
class testHandler (pHandler):
def get (self):
bucket = '/my_bucket'
filename = '/pdf/somedoc.pdf'
user = users.get_current_user()
if user:
pdf = gcs.open(bucket+filename)
self.write(pdf.read())
答案 1 :(得分:1)
即使是PO回答了他的问题,也只是想补充几点想法。
PO的代码是将pdf文件的内容写入http响应。
self.write(pdf.read())
根据GAE quota limitation,如果响应大小大于32MB,则会失败。
此外,最好设置urlfetch_timeout值,因为在某些情况下默认值5秒可能不够,并且会导致DeadlineExceededError。
我建议您在收到请求时尝试使用Google Cloud Storage API(不是GAE)将copy文件发送到临时位置。还要确保将新对象的acl设置为公共可读,然后提供新对象的公共URL。
此外,向任务队列发送请求,将任务的eta设置为您选择的超时值。执行任务后,从临时位置删除该文件,以便无法再访问该文件。
更新:
使用Service Account Auth,生成新的JSON密钥,获取私钥。
将范围设置为FULL_CONTROL,因为我们需要更改acl设置。
我在工作时还没有测试代码。但是,当我有时间的时候会这样做。
import httplib2
from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.client import SignedJwtAssertionCredentials
# Need to modify ACL, therefore need full control access
GCS_SCOPE = 'https://www.googleapis.com/auth/devstorage.full_control'
def get_gcs_client( project_id,
service_account=None,
private_key=None):
credentials = SignedJwtAssertionCredentials(service_account, private_key, scope=GCS_SCOPE)
http = httplib2.Http()
http = credentials.authorize(http)
service = build('storage', 'v2', http=http)
return service
答案 2 :(得分:0)
我认为您最好在GCS上使用BlobStore API来提供此类文件。基于Using the Blobstore API with Google Cloud Storage,我提出了这种方法:
import cloudstorage as gcs
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
GCS_PREFIX = '/gs'
BUCKET = '/my_bucket'
FILE = '/pdf/somedoc.pdf'
BLOBSTORE_FILENAME = GCS_PREFIX + BUCKET + FILE
class GCSWebAppHandler(webapp2.RequestHandler):
def get(self):
blob_key = blobstore.create_gs_key(BLOBSTORE_FILENAME)
self.response.headers['Content-Type'] = 'application/pdf'
self.response.write(blobstore.fetch_data(blob_key, 0, blobstore.MAX_BLOB_FETCH_SIZE - 1))
class GCSBlobDlHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self):
blob_key = blobstore.create_gs_key(BLOBSTORE_FILENAME)
self.send_blob(blob_key)
app = webapp2.WSGIApplication([
('/webapphandler', GCSWebAppHandler),
('/blobdlhandler', GCSServingHandler)],
debug=True)
如您所见,您可以在此处使用两个示例处理程序,webapphandler
和blobdlhandler
。使用后者可能会更好,因为前者受MAX_BLOB_FETCH_SIZE
中fetch_data()
的限制,即1MB,但如果您提供的文件小于此大小,则可以