关于python:在Google App Engine中上传文件

关于python:在Google App Engine中上传文件

Upload files in Google App Engine

我打算创建一个Web应用程序,允许用户降级Visual Studio项目文件。 但是,似乎Google App Engine可以通过db.TextPropertydb.BlobProperty在Google服务器上接受文件上传和平面文件存储。

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


实际上,该问题在App Egnine文档中得到了回答。请参阅有关上传用户图像的示例。

中的HTML代码:

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

Python代码:

1
2
3
4
5
6
7
8
9
10
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('/')

这是一个完整的工作文件。我从Google网站上提取了原始图片,并对其进行了修改,使其更加真实。

注意事项:

  • 此代码使用BlobStore API
  • 此行的目的是
    ServeHandler类用于"修复"
    键,使其摆脱任何名称
    可能发生在
    浏览器(我没有在
    铬)

    1
    blob_key = str(urllib.unquote(blob_key))
  • 最后的" save_as"子句很重要。它将确保文件名在发送到浏览器时不会被篡改。摆脱它,观察会发生什么。

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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    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"> <input type="submit" name="submit" value="Submit"> </form></body></html>""")

            for b in blobstore.BlobInfo.all():
                self.response.out.write('
    <li>
    '
    + str(b.filename) + '')

    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()


    Google网上论坛对此有一个话题:

    上载档案

    有了很多有用的代码,该讨论对我上载文件有很大帮助。


    我今天尝试,它的工作方式如下:

    我的SDK版本是1.3.x

    html页面:

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

    服务器代码:

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

    Google发布了一项用于存储大文件的服务。看看blobstore API文档。如果文件> 1MB,则应使用它。


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

    没有:

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

    是:

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


    我个人发现,此处所述的教程在将GAE与Java运行时结合使用时非常有用。由于某些原因,当我尝试使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    <form action="/testservelet" method="get" enctype="multipart/form-data">
       
            Myfile:<input type="file" name="file" size="50"/>
       

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

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


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

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

    1
    2
    3
    4
    5
    class MyModel(db.Model):
      blob = db.BlobProperty()

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

    有一种使用平面文件系统的方法(用法方面为Atleast)

    有这个Google App Engine虚拟文件系统项目。可以借助数据存储区和内存缓存API来实现,以模拟普通文件系统。使用此库,您可以在项目中使用类似的文件系统访问(读取和写入)。


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

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

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

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

    img_contents变量在Google Chrome中是str(),但在Firefox中是unicode。和现在一样,db.Blob()构造函数采用一个字符串,如果传入unicode字符串,则会引发错误。

    有谁知道如何解决?

    另外,我发现绝对奇怪的是,当我复制并粘贴Guestbook应用程序(带有头像)时,它可以完美运行。我在代码中完全按照相同的方式进行操作,但无法正常工作。我离拔头发很近。


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

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

    DataStore条目的限制为1MB,这可能会或可能不会成为问题。


    推荐阅读