diff --git a/appengine/blobstore/__init__.py b/appengine/blobstore/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/appengine/blobstore/app.yaml b/appengine/blobstore/app.yaml new file mode 100644 index 000000000000..636a04bae7e2 --- /dev/null +++ b/appengine/blobstore/app.yaml @@ -0,0 +1,8 @@ +runtime: python27 +api_version: 1 +threadsafe: yes + +handlers: +- url: .* + script: main.app + login: required diff --git a/appengine/blobstore/main.py b/appengine/blobstore/main.py new file mode 100644 index 000000000000..70b18adb6f57 --- /dev/null +++ b/appengine/blobstore/main.py @@ -0,0 +1,80 @@ +# Copyright 2015 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# [START all] +import webapp2 + +from google.appengine.api import users +from google.appengine.ext import blobstore +from google.appengine.ext import ndb +from google.appengine.ext.webapp import blobstore_handlers + + +# This datastore model keeps track of which users uploaded which photos. +class UserPhoto(ndb.Model): + user = ndb.StringProperty() + blob_key = ndb.BlobKeyProperty() + + +class PhotoUploadFormHandler(webapp2.RequestHandler): + def get(self): + # [START upload_url] + upload_url = blobstore.create_upload_url('/upload_photo') + # [END upload_url] + # [START upload_form] + # To upload files to the blobstore, the request method must be "POST" + # and enctype must be set to "multipart/form-data". + self.response.out.write(""" +
+ +""".format(upload_url)) + # [END upload_form] + + +# [START upload_handler] +class PhotoUploadHandler(blobstore_handlers.BlobstoreUploadHandler): + def post(self): + try: + upload = self.get_uploads()[0] + user_photo = UserPhoto( + user=users.get_current_user().user_id(), + blob_key=upload.key()) + user_photo.put() + + self.redirect('/view_photo/%s' % upload.key()) + + except: + self.error(500) +# [END upload_handler] + + +# [START download_handler] +class ViewPhotoHandler(blobstore_handlers.BlobstoreDownloadHandler): + def get(self, photo_key): + if not blobstore.get(photo_key): + self.error(404) + else: + self.send_blob(photo_key) +# [END download_handler] + + +app = webapp2.WSGIApplication([ + ('/', PhotoUploadFormHandler), + ('/upload_photo', PhotoUploadHandler), + ('/view_photo/([^/]+)?', ViewPhotoHandler), +], debug=True) +# [END all] diff --git a/appengine/blobstore/main_test.py b/appengine/blobstore/main_test.py new file mode 100644 index 000000000000..53d6642e23a3 --- /dev/null +++ b/appengine/blobstore/main_test.py @@ -0,0 +1,31 @@ +# Copyright 2015 Google Inc. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import tests +import webtest + +from . import main + + +class TestBlobstoreSample(tests.AppEngineTestbedCase): + + def setUp(self): + super(TestBlobstoreSample, self).setUp() + self.app = webtest.TestApp(main.app) + + def test_form(self): + self.loginUser() + response = self.app.get('/') + + self.assertTrue('/_ah/upload' in response) diff --git a/tests/utils.py b/tests/utils.py index f033b1c2a9be..41741591b495 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -88,6 +88,7 @@ def setUp(self): self.testbed.init_memcache_stub() # Setup remaining stubs. + self.testbed.init_blobstore_stub() self.testbed.init_user_stub() self.testbed.init_taskqueue_stub(root_path='tests/resources') self.taskqueue_stub = self.testbed.get_stub(