Reputation: 12007
I have successfully been able to upload images to my Google App Engine Blobstore using the provided code here (in one of the comments, which is majorly based on the GAE docs).
Here is the full code for reference:
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>""")
for b in blobstore.BlobInfo.all():
self.response.out.write('<li><a href="/serve/%s' % str(b.key()) + '">' + str(b.filename) + '</a>')
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()
However, this code requires that the upload url be created on a GET
request prior to POST
request containing the image data:
def get(self):
upload_url = blobstore.create_upload_url('/upload')
When I try to send the image from a mobile device, I'd like to push the server code into a single code-block under the def post(self):
function, and I'm having trouble doing this.
Moving the above line into the def post(self):
code doesn't seem to do the trick.
Any ideas?
Cheers! Brett
Upvotes: 3
Views: 800
Reputation: 2035
yes you can make it one single block of code using urlfetch. Here is my approach:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file')
if len(upload_files) > 0 :
blob_info = upload_files[0]
self.response.write(str(blob_info.key()))
else:
self.error(404)
class SomeHandler(webapp.RequestHandler):
def post(self):
file = self.request.POST.get('file')
if (file is not None):
# Use urlfetch to call to the blob upload url and get result
# Just copy the same request body and header and pass to UploadHandler here
result = urlfetch.fetch(
url= blobstore.create_upload_url('/upload'),
payload=self.request.body,
method=urlfetch.POST,
headers=self.request.headers)
if result.status_code == 200:
blob_key_str = result.content
# Get blob key
blob_key = blobstore.BlobKey(blob_key_str)
# Maybe a url for the file
blob_url = images.get_serving_url(blob_key_str, 400)
This way you can always Upload file to SomeHandler rather than have to obtain the upload URL first then only Upload.
Hope it helps!
Upvotes: 2
Reputation: 80340
This will not work with the default Blobstore upload handler: it needs two requests: first to create a one-time download url and the second to actually do POST to this url.
If you want to do all in one go, create your own file upload handler and use new Blobstore API to write files.
Upvotes: 0