2009年11月22日日曜日

Google app engine(python)でアップローダーを作る。

参考ページ

全体的に参考ページを真似した。読んでて感動した。すごいお方もいるんだなぁ…

解決できなかったこと:
日本語のファイル名ではエラーが出る。
# -*- coding : utf-8 -*-

from google.appengine.ext import webapp
from google.appengine.ext import db
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import users

class FileStore(db.Model):
  #ほとんど使ってません。
  name = db.StringProperty()
  
  body = db.BlobProperty()
  
  mime = db.StringProperty()
  
  size = db.IntegerProperty()
  
  time = db.DateTimeProperty(auto_now_add=True)
  
  download_count = db.IntegerProperty()

class RenderMainPage(webapp.RequestHandler):
  def get(self):
    user = users.get_current_user()
    if user:
      self.response.out.write(
      """
      <html>
        <body>
          <div style="border-bottom: 1px dotted gray;">
            <nobr>
              <b>%(nickname)s</b>
              <a href='%(logout_url)s'>logout</a>
              <a href='/alldelete'>All Delete</a>
            </nobr>
          </div>
          <br>
          <div style="background-color: #ece8e3;border: 1px dotted #82c78e;padding: 3px;">
            <h4>upload</h4>
              <form action='/upload' method='post' enctype='multipart/form-data'>
                password: <input type='text' name="admin_pass" /><br>
                <input type='file' name="file" />
                <input type="submit" value="upload" />
              </form>
          </div>
          <br>
          <div style="background-color: #efebe7;padding: 3px;">
            <h3 style="text-align: center;">download</h3>
          <br>
      """ %{"nickname": user.nickname(),
            "logout_url": users.create_logout_url("/")})
    
      files = db.GqlQuery("SELECT * FROM FileStore"+
                          " ORDER BY time DESC")
      if not files:
        self.response.out.write("not upload file")
        return
      else:
        for file_data in files:
          if file_data.name:
            self.response.out.write(
            """
              <a href='/download?key=%(key)s'>%(name)s</a><br>
            """ %{"key": str(file_data.key()),
                  "name": file_data.name
                  })
      self.response.out.write(
      """
         </div>
        </body>
      </html>
      """)
    else:
      self.response.out.write(
      """
      <html>
        <body>
          <a href='%s'>Sign In</a>
        </body>
      </html>
      """ % users.create_login_url("/"))

class Uploader(webapp.RequestHandler):
  def post(self):
    if self.request.get("admin_pass") == "xxxxxxxx":#自分以外アップロードできません。
      file_data = self.request.get("file")
      upf = self.request.body_file.vars["file"]# omit upload file
      _file = FileStore()
      
      _file.name = upf.filename
      _file.body = db.Blob(file_data)
      _file.mime = upf.headers["content-type"]
      _file.size = len(_file.body)
      _file.download_count = 0
      _file.put()
      
      self.redirect("../")
    else:
      self.redirect("../")
      
class Downloader(webapp.RequestHandler):#知識がない分、ここが一番参考になった。
  def get(self):
    _file = FileStore.get(self.request.get("key"))
    #アップローダを作るとき重要となる部分.
    self.response.headers["Content-Type"] = "application/octet-stream"#このContent-Typeが必要。
    content_disposition = 'attachment; filename="%s"' % str(_file.name)
    self.response.headers["Content-Disposition"] = content_disposition #これも必須
      
    self.response.out.write(_file.body) #バイナリの書き出し

class AllDelete(webapp.RequestHandler):#テストを手っ取り早くするためもの。データストアを全削除する。
  def get(self):
    file_list = db.GqlQuery("SELECT * FROM FileStore")
    for _file in file_list:
      _file.delete()
      
    self.redirect("../")  
    
application = webapp.WSGIApplication([
  ("/", RenderMainPage),
  ("/upload", Uploader),
  ("/download", Downloader),
  ("/alldelete", AllDelete)
], debug=True)

def main():
  run_wsgi_app(application)

if __name__ == "__main__":
  main()

1 件のコメント:

  1. Normally I don't read article on blogs, but I wish to say that this write-up very forced me to try and do it! Your writing style has been amazed me. Thanks, quite nice post.

    Here is my web site;

    返信削除