Python 在谷歌应用程序引擎中上传文件

Python 在谷歌应用程序引擎中上传文件,python,google-app-engine,Python,Google App Engine,我计划创建一个web应用程序,允许用户降级他们的VisualStudio项目文件。然而,Google App Engine似乎通过db.TextProperty和db.BlobProperty接受在Google服务器上上传文件和存储平面文件 我很高兴任何人都能提供代码示例(客户端和服务器端)来说明如何做到这一点。您不能存储文件,因为没有传统的文件系统。您只能将它们存储在它们自己的数据存储中(在定义为的字段中) 上一个链接中有一个示例: class MyModel(db.Model): blo

我计划创建一个web应用程序,允许用户降级他们的VisualStudio项目文件。然而,Google App Engine似乎通过
db.TextProperty
db.BlobProperty
接受在Google服务器上上传文件和存储平面文件


我很高兴任何人都能提供代码示例(客户端和服务器端)来说明如何做到这一点。

您不能存储文件,因为没有传统的文件系统。您只能将它们存储在它们自己的数据存储中(在定义为的字段中)

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

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

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

Google应用程序引擎中没有平面文件存储。所有东西都必须进入数据库,它有点像关系数据库,但不完全是

您可以将文件存储为或属性


数据存储条目有1MB的限制,这可能是一个问题,也可能不是问题。

Google群组中有一个关于它的线程:


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

事实上,这个问题在App-Egnine文档中得到了回答。请参见上的示例

HTML代码,内部:

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('/') 类留言簿(webapp.RequestHandler): def post(自我): 问候语 if users.get_current_user(): greeting.author=users.get_current_user() greeting.content=self.request.get(“内容”) avatar=self.request.get(“img”) greeting.avatar=db.Blob(avatar) 问候语
self.redirect(“/”)如果仍有问题,请检查是否正在表单标记中使用enctype

否:


是的:


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

<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”属性的表单。删除它是可行的,但这意味着我不能上传任何文件。

谷歌发布了一项存储大型文件的服务。看一看。如果您的文件大于1MB,您应该使用它。

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

我的sdk版本是1.3.x

html页面:

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

我在appengine上上传文件时观察到一些奇怪的行为。提交以下表格时:

<form method="post" action="/upload" enctype="multipart/form-data">
    <input type="file" name="img" />
    ...
</form>
img\u contents
变量在Google Chrome中是一个
str()
,但在Firefox中是unicode。正如您现在看到的,
db.Blob()
构造函数接受一个字符串,如果您传入一个unicode字符串,它将抛出一个错误

有人知道如何解决这个问题吗


另外,我发现非常奇怪的是,当我复制并粘贴留言簿应用程序(带有虚拟角色)时,它工作得非常完美。在我的代码中,我用完全相同的方式做每件事,但它就是不起作用。我马上就要把头发拔出来了。

这是一个完整的工作文件。我从谷歌网站上调出了原稿,并对其进行了修改,使其更真实一些

需要注意的几件事:

  • 此代码使用
  • 该行在 ServeHandler类用于“修复” 键,这样它就可以去掉任何名称 可能已在中发生的损坏 浏览器(我没有观察到任何 铬)

  • 最后的“另存为”条款很重要。它将确保文件名在发送到浏览器时不会损坏。摆脱它,观察发生了什么

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

    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()
    
    导入操作系统
    导入URL库
    从google.appengine.ext导入blobstore
    从google.appengine.ext导入webapp
    从google.appengine.ext.webapp导入blobstore\u处理程序
    从google.appengine.ext.webapp导入模板
    从google.appengine.ext.webapp.util导入运行\u wsgi\u应用程序
    类MainHandler(webapp.RequestHandler):
    def get(自我):
    上传url=blobstore。创建上传url('/upload')
    self.response.out.write(“”)
    self.response.out.write(“”%upload\u url)
    self.response.out.write(““上载文件:
    ”) 对于blobstore.BlobInfo.all()中的b: self.response.out.write(“
  • ”) 类UploadHandler(blobstore\u Handler.BlobstoreUploadHandler): def post(自我): upload\u files=self.get\u uploads('文件') blob\u info=上载\u文件[0] self.redirect(“/”) 类ServeHandler(blobstore\u Handler.BlobstoreDownloadHandler): def get(自身,blob_键): blob_key=str(urllib.unquote(blob_key)) 如果不是blobstore.get(blob_键): 自我错误(404) 其他: self.send\u blob(blobstore.BlobInfo.get(blob\u键),save\u as=True) def main(): application=webapp.WSGIApplication( [(“/”,MainHandler), ('/upload',UploadHandler), ('/serve/([^/]+)?',ServeHandler), ],debug=True) 运行应用程序(应用程序) 如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu': main()
  • 有一种使用平面文件系统的方法(至少从使用角度来看)


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

    可能是因为您使用的是get方法,请尝试将其设置为post。我不确定它是否能工作,但值得一试。在我实现你的回答之前,我遇到了一个编码错误。当我这样做时,一个真正让我恼火的障碍是没有包括文件输入类型的“大小”。我使用Safari进行测试,默认情况下,Safari的文件长度很短(?),而我在GAE中得到的文件内容只是文件名。这只是一个警告,可能会让人稍微头疼一点。:D表单说:mutlipart/formdata而不是multipart/formdata。Chrome足够聪明,可以纠正打字错误,Firefox则不行。如果你不喜欢这种方法,就会丢失mime类型信息。@santiagobasulto:为什么不呢
    file_contents = self.request.POST.get('myfile').file.read() 
    
    <form method="post" action="/upload" enctype="multipart/form-data">
        <input type="file" name="img" />
        ...
    </form>
    
    img_contents = self.request.get('img')
    
    blob_key = str(urllib.unquote(blob_key))
    
    self.send_blob(blobstore.BlobInfo.get(blob_key), save_as=True)
    
    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()