http://blog.notdot.net/2009/9/Handling-file-uploads-in-App-Engine
http://hi.baidu.com/zjm1126/item/31d65e31962da022b3c0c56e
import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class MyModel(db.Model):
data = db.BlobProperty(required=True)
mimetype = db.StringProperty(required=True)
class BaseRequestHandler(webapp.RequestHandler):
def render_template(self, filename, template_args=None):
if not template_args:
template_args = {}
path = os.path.join(os.path.dirname(__file__), 'templates', filename)
self.response.out.write(template.render(path, template_args))
class upload(BaseRequestHandler):
def get(self):
self.render_template('index.html',)
def post(self):
file = self.request.POST['file']
obj = MyModel(data=file.value, mimetype=file.type)
obj.put()
o=file
#self.response.out.write(''.join('%s: %s <br/>' % (a, getattr(o, a)) for a in dir(o)))
#return
file_url = "http://%s/download/%d/%s" % (self.request.host, obj.key().id(), file.filename)
self.response.out.write("Your uploaded file is now available at <a href='%s'>%s</a>" % (file_url,file_url,))
class download(BaseRequestHandler):
def get(self,id,filename):
#id=self.request.get('id')
entity = MyModel.get_by_id(int(id))
self.response.headers['Content-Type'] = entity.mimetype
self.response.out.write(entity.data)
application = webapp.WSGIApplication(
[
('/?', upload),
('/download/(\d+)/(.*)',download),
],
debug=True
)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
the html is:
<form enctype="multipart/form-data" action="/" method="post">
<input type="file" name="file" />
<input type="submit" />
</form>
This is the ninth in a series of 'Cookbook' posts describing usefulstrategies and functionality for writing better App Engine applications.
One issue that comes up frequently on the App Engine groups is how tohandle file uploads from users. Part of the confusion arises from thefact that App Engine apps cannot write to the local filesystem.Fortunately, the Datastore comes to the rescue: We can easily write anapp that accepts file uploads and stores them in the datastore, thenserves them back to users.
To start, we need an HTML form users can upload files through:
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form method="post" action="/">
<input type="file" name="file" />
<input type="submit" value="Upload" />
</form>
</body>
</html>
We'll also need a datastore model we can store the uploaded file in:
class DatastoreFile(db.Model):
data = db.BlobProperty(required=True)
mimetype = db.StringProperty(required=True)
And finally, a Request Handler that can handle the uploads:
class UploadHandler(webapp.RequestHandler):
def get(self):
self.response.out.write(template.render("upload.html", {}))
def post(self):
file = self.request.POST['file']
entity = DatastoreFile(data=file.value, mimetype=file.type)
entity.put()
file_url = "http://%s/%d/%s" % (self.request.host, entity.key().id(), file.name)
self.response.out.write("Your uploaded file is now available at %s" % (file_url,))
Note that we access the uploaded file using self.request.POST ratherthan self.request.get(); using self.request.get("file") would only giveus the actual data of the uploaded file, whilstself.request.POST["file"] returns a cgi.FieldStorage object, whichgives us access to the file data, filename, and mimetype. We take careto store the mimetype in addition to the original file data so we canmake sure we serve it back up with the correct mimetype.
Serving the uploaded file from the datastore is, of course, also easy:
class DownloadHandler(webapp.RequestHandler):
def get(self, id, filename):
entity = DatastoreFile.get_by_id(int(id))
self.response.headers['Content-Type'] = entity.mimetype
self.response.out.write(entity.data)
Our handler here takes a filename in addition to the ID; the filenameis purely for convenience, to make the URLs we provide more friendly.All we care about is the ID, which we use to find the file object inthe datastore.
Finally, here's the webapp to glue all this together:
application = webapp.WSGIApplication([
('/', UploadHandler),
('/(\d+)/(.*)', DownloadHandler),
])
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
Next, we'll be taking a break from the cookbook series, and workingthrough the steps of building a blogging system on App Engine.