App Engine cannot:
- write to the file system. Applications must use the App Engine data store to store persistent data.
What you need to do is submit the form with the file upload field to the user.
When the form is submitted, the file is downloaded, and Blobstore creates a blob from the contents of the file and returns the blob key, useful for retrieving and serving the blob later.
The maximum size of an object is 2 gigabytes.
Here is a working snippet you can try:
#!/usr/bin/env python # 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>""") class UploadHandler(blobstore_handlers.BlobstoreUploadHandler): def post(self): upload_files = self.get_uploads('file') blob_info = upload_files[0] self.redirect('/serve/%s' % blob_info.key()) class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler): def get(self, resource): resource = str(urllib.unquote(resource)) blob_info = blobstore.BlobInfo.get(resource) self.send_blob(blob_info) def main(): application = webapp.WSGIApplication( [('/', MainHandler), ('/upload', UploadHandler), ('/serve/([^/]+)?', ServeHandler), ], debug=True) run_wsgi_app(application) if __name__ == '__main__': main()
EDIT1:
in your specific case, you can use BlobProperty (limited to 1 MB) to store your request:
class Photo(db.Model): imageblob = db.BlobProperty()
then adapt your webapp.RequestHandler to save your request:
class Upload(webapp.RequestHandler): def post(self): image = self.request.get("Filedata") photo = Photo() photo.imageblob = db.Blob(image) photo.put()
EDIT2:
You do not need to change the app.yaml application, just add a new handler and map it in your WSGI. To get a saved photo, you must add another handler to serve your photos:
class DownloadImage(webapp.RequestHandler): def get(self): photo= db.get(self.request.get("photo_id")) if photo: self.response.headers['Content-Type'] = "image/jpeg" self.response.out.write(photo.imageblob) else: self.response.out.write("Image not available")
then map the new DownloadImage class:
application = webapp.WSGIApplication([ ... ('/i', DownloadImage), ... ], debug=True)
You could get the images using a url like this:
yourapp/i?photo_id = photo_key
As requested, if for some odd reason you really want to serve your images using this type of URL www.mysite.com/i/photo_key.jpg , you can try:
class Download(webapp.RequestHandler): def get(self, photo_id): photo= db.get(db.Key(photo_id)) if photo: self.response.headers['Content-Type'] = "image/jpeg" self.response.out.write(photo.imageblob) else: self.response.out.write("Image not available")
with slightly different display:
application = webapp.WSGIApplication([ ... ('/i/(\d+)\.jpg', DownloadImage), ... ], debug=True)