在Google App Engine中上传文件

时间:2008-09-17 09:28:53

标签: python google-app-engine

我计划创建一个允许用户降级其visual studio项目文件的Web应用程序。但是,Google App Engine似乎通过db.TextPropertydb.BlobProperty接受文件上传和平面文件存储在Google服务器上。

我很高兴有人可以提供代码示例(客户端和服务器端)如何完成。

11 个答案:

答案 0 :(得分:49)

事实上,App Egnine文档中回答了这个问题。请参阅Uploading User Images上的示例。

HTML代码,在< form>< / form>内:

<input type="file" name="img"/>

Python代码:

class Guestbook(webapp.RequestHandler):
  def post(self):
    greeting = Greeting()
    if users.get_current_user():
      greeting.author = users.get_current_user()
    greeting.content = self.request.get("content")
    avatar = self.request.get("img")
    greeting.avatar = db.Blob(avatar)
    greeting.put()
    self.redirect('/')

答案 1 :(得分:42)

这是一个完整的工作文件。我从谷歌网站上取下了原版并进行了修改,使其更加真实。

需要注意的一些事项:

  1. 此代码使用BlobStore API
  2. 此行的目的在于 ServeHandler类是“修复”的 键,以便它摆脱任何名称 可能发生过的错误 浏览器(我没有观察到任何内容 铬)

    blob_key = str(urllib.unquote(blob_key))
    
  3. 最后的“save_as”子句非常重要。它将确保文件名在发送到您的浏览器时不会被破坏。摆脱它来观察会发生什么。

    self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
    
  4. 祝你好运!

    import os
    import urllib
    
    from google.appengine.ext import blobstore
    from google.appengine.ext import webapp
    from google.appengine.ext.webapp import blobstore_handlers
    from google.appengine.ext.webapp import template
    from google.appengine.ext.webapp.util import run_wsgi_app
    
    class MainHandler(webapp.RequestHandler):
        def get(self):
            upload_url = blobstore.create_upload_url('/upload')
            self.response.out.write('<html><body>')
            self.response.out.write('<form action="%s" method="POST" enctype="multipart/form-data">' % upload_url)
            self.response.out.write("""Upload File: <input type="file" name="file"><br> <input type="submit" name="submit" value="Submit"> </form></body></html>""")
    
            for b in blobstore.BlobInfo.all():
                self.response.out.write('<li><a href="/serve/%s' % str(b.key()) + '">' + str(b.filename) + '</a>')
    
    class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
        def post(self):
            upload_files = self.get_uploads('file')
            blob_info = upload_files[0]
            self.redirect('/')
    
    class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
        def get(self, blob_key):
            blob_key = str(urllib.unquote(blob_key))
            if not blobstore.get(blob_key):
                self.error(404)
            else:
                self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
    
    def main():
        application = webapp.WSGIApplication(
              [('/', MainHandler),
               ('/upload', UploadHandler),
               ('/serve/([^/]+)?', ServeHandler),
              ], debug=True)
        run_wsgi_app(application)
    
    if __name__ == '__main__':
      main()
    

答案 2 :(得分:10)

Google网上论坛中有一个关于它的主题:

Uploading Files

有很多有用的代码,这个讨论对我上传文件非常有帮助。

答案 3 :(得分:6)

Google发布了一项存储大型文件的服务。看看blobstore API documentation。如果您的文件是&gt; 1MB,你应该使用它。

答案 4 :(得分:6)

我今天尝试,它的工作原理如下:

我的sdk版本是1.3.x

html页面:

<form enctype="multipart/form-data" action="/upload" method="post" > 
<input type="file" name="myfile" /> 
<input type="submit" /> 
</form> 

服务器代码:

file_contents = self.request.POST.get('myfile').file.read() 

答案 5 :(得分:3)

如果您仍有问题,请检查您是否在表单标记中使用了enctype

没有

<form encoding="multipart/form-data" action="/upload">

是:

<form enctype="multipart/form-data" action="/upload">

答案 6 :(得分:1)

由于没有传统的文件系统,您无法存储文件。您只能将它们存储在自己的DataStore中(在定义为BlobProperty的字段中)

上一个链接中有一个例子:

class MyModel(db.Model):
  blob = db.BlobProperty()

obj = MyModel()
obj.blob = db.Blob( file_contents )

答案 7 :(得分:1)

我个人发现在使用GAE的Java运行时时,here描述的教程非常有用。出于某种原因,当我尝试使用

上传文件时
<form action="/testservelet" method="get" enctype="multipart/form-data">
    <div>
        Myfile:<input type="file" name="file" size="50"/>
    </div>

    <div>
        <input type="submit" value="Upload file">
    </div>
</form>

我发现我的HttpServlet类由于某种原因不接受带有'enctype'属性的表单。但删除它有效,这意味着我无法上传任何文件。

答案 8 :(得分:0)

Google App Engine中没有存储平面文件。一切都必须进入Datastore,这有点像关系数据库但不完全。

您可以将文件存储为TextPropertyBlobProperty属性。

DataStore条目有1MB的限制,这可能是也可能不是问题。

答案 9 :(得分:0)

我在App Engine上传文件时发现了一些奇怪的行为。当您提交以下表格时:

<form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" name="img" />
    ...
</form>

然后从请求中提取img,如下所示:

img_contents = self.request.get('img')

img_contents变量是Google Chrome中的str(),但它是Firefox中的unicode。就像你现在一样,db.Blob()构造函数接受一个字符串,如果你传入一个unicode字符串会抛出一个错误。

有谁知道如何解决这个问题?

另外,我觉得非常奇怪的是,当我复制并粘贴留言簿应用程序(带有头像)时,它完美无缺。我在代码中以完全相同的方式执行所有操作,但它无法正常工作。我非常接近拔头发。

答案 10 :(得分:0)

有一种方法可以使用平面文件系统(Atleast in usage perspective)

Google App Engine Virtual FileSystem project。这是在数据存储区和memcache API的帮助下实现的,以模拟普通的文件系统。使用此库,您可以在项目中使用类似的文件系统访问(读取和写入)