我正在应用引擎上构建一个应用程序,让用户上传一个文件,然后由应用程序执行操作.文件的大小通常约为几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搜索的提示,但是我不太了解这与我的情况有什么关系,特别是将上传文件的内容读入内存以便我可以将其写入云存储.
如果你知道它是如何完成的,这可能是世界上最简单的事情,但如果没有人在代码中向我展示它是如何完成的,我就无法做到:-(
谢谢
编辑:@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">
解决方法
由于上传的文件可能较大,因此您不希望在App Engine中处理上传,而是将文件直接上传到Google云端存储.
这可以做到,而且并不太难.
实际上,这正是07000中给出的例子.
可能令人困惑的是,当您希望云存储中的文件时,该示例引用Blobstore – 但它没关系 – 从1.7.0版开始,您可以执行以下操作:
upload_url = blobstore.create_upload_url('/upload',gs_bucket_name='my_bucket')
(而不是我链接的示例中的第1步),上传网址将直接上传到云端存储.
现在,您的表单操作应该是blobstore.create_upload_url函数返回的字符串upload_url.
表单完成处理(意味着文件已上载)后,它将重定向到您传递给该函数的参数(在示例中为/ upload).
您不需要编写自己的POST处理函数,如问题中所述.