我确信这个问题的答案很简单,但对我来说,事实证明这是非常令人沮丧的,因为我无法将任何我已经找到的解决方案放到我自己使用的实用代码中。
我正在app引擎上构建一个应用程序,让用户上传一个文件,然后由应用程序执行操作。文件的大小通常约为几Mbs,在某些情况下可能高达20 Mb左右。这足以触发应用程序引擎中的30秒超时,因此我尝试按照各种网站(包括此处)的建议直接上传到云存储。
我的表单的上传部分如下所示:
<form name="convert" action="/transform" method="post" enctype="multipart/form-data">
<input type="file" name="coords">
<input type="submit" name="submit" value="Transform">
</form>
处理程序看起来像这样(我只是开始使用app引擎,所以如果这看起来很愚蠢,请道歉。
class TransformPage(BaseHandler):
def get(self):
self.render_template('transform.html',name=self.request.get('form'))
def post(self):
filename = self.request.POST['coords'].filename
filesize = int(self.request.headers['Content_Length'])
if filesize>5242880:
self.redirect('/error')
else:
save_to_cloud(file.value,filename)
# Start processing file here
我检查文件大小是一种防止30秒超时的非常简单的方法,5Mb似乎是我在网络上30秒内可以推进的最大大小。
save_to_cloud()只是我围绕Google云存储API编写的包装器,看起来像这样:
def save_to_cloud(f,filename):
filename = BUCKET + filename
create_file_and_write(f,filename)
以上都可行,我看到上传的文件最终存在于云端存储中,但正如我上面所述,分解为更大的文件。 我已经看到了关于使用create_upload_url搜索的提示,但是我不太了解这与我的情况有什么关系,特别是将上传文件的内容读入内存,以便我可以将其写入云存储。 / p>
如果您知道它是如何完成的,这可能是世界上最容易的事情,但如果没有人在代码中向我展示如何完成它,我就无法做到: - (
由于
编辑:@Itamar:这确实是我想要完成的,尽管上传表单还包含一些用户做出的其他选择。我现在已将代码更改为此
class TransformPage(BaseHandler):
def get(self):
upload_url =blobstore.create_upload_url('/upload',gs_bucket_name='/my_bucket/')
self.render_template('transform.html',
{'name':self.request.get('form'),
{'upload_url':upload_url})
但是我无法将upload_url显示在模板html中,看起来像这样
<form name="convert" action="{{ upload_url }}" method="post" enctype="multipart/form-data">
答案 0 :(得分:9)
如果我理解正确,您尝试做的是从App Engine提供表单,允许用户选择要上传的文件。 由于上传的文件可能较大,因此您不想在App Engine中处理上传,而是将文件直接上传到Google云端存储。
这可以做到,而且并不太难。 实际上,这正是App Engine Python Blobstore docs中给出的例子。 可能令人困惑的是,当您希望云存储中的文件时,该示例引用Blobstore - 但它没关系 - 从1.7.0版开始,您可以执行此操作:
upload_url = blobstore.create_upload_url('/upload', gs_bucket_name='my_bucket')
(而不是我链接的示例中的第1步),上传网址将直接上传到云存储。
现在,您的表单操作应该是upload_url
函数返回的字符串blobstore.create_upload_url
。
表单完成处理(意味着上传文件)后,它将重定向到您传递给该函数的参数(在示例中为/upload
)。
您不需要编写自己的POST处理函数,如问题所述。
答案 1 :(得分:0)
我创建了一个关于如何上传和使用GCS文件的要点:https://gist.github.com/voscausa/9541133
这是处理多部分表单帖子的代码:
class GcsUpload(webapp2.RequestHandler):
def post(self):
field_storage = self.request.POST.get("file", None)
if isinstance(field_storage, cgi.FieldStorage):
file_name = field_storage.filename
dyn = gcs_data.Dynamics(id=file_name, filename=file_name)
gcs_file_name = gcs_data.gcs_write_blob(dyn, field_storage.file.read())
gcs_data.gcs_serving_url(dyn)
dyn.put()
logging.info('Uploaded and saved in default GCS bucket : ' + gcs_file_name)
self.response.headers[b'Content-Type'] = gcs_data.gcs_content_type(dyn)
self.response.write(gcs_data.gcs_read_blob(dyn))
else:
logging.error('GCS Upload failed')