Uploading images - Google App Engine + Python - python

I'm using this link as an example to uploading images:
https://gist.github.com/jdstanhope/5079277
My HTML code:
<form action="/upload_image" method="post" id="form1" runat="server">
<div class="fileButtons">
<input type='file' id="imgInp" name="imgInput" accept="image/*"/><br><br>
<input type='button' id='remove' value='Remove' />
</div></form>
main.py:
class SetImage(webapp2.RequestHandler):
def post(self):
logging.debug("test")
id = str(self.request.get('id'))
image = self.request.get('imgInput')
app = webapp2.WSGIApplication([('/upload_image', SetImage),
('/', MainPage)], debug=True)
But when I add an image, nothing is being done, and the log console doesn't print:
logging.debug("test")

The recommended way of uploading images to GAE is by using blobstore.
Here is a quick breakdown of the doc to help you achieve this fast:
Imports:
import os
import urllib
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
Serve the form HTML. this form performs the POST to GAE with the selected files data:
class MainHandler(webapp2.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>""")
Add a handler for receiving the POST data (binary content of the file). the last line in this function is to redirect the response to the location from where the file could be downloaded:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
# 'file' is file upload field in the form
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
self.redirect('/serve/%s' % blob_info.key())
Add handler to serve the image that you uploaded using the UploadHandler described above:
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)
And finally, define the routes for the app:
app = webapp2.WSGIApplication([('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler)],
debug=True)

Regarding the issue of your log statement not firing: The default log level for dev_appserver.py is info, which you can override with the --dev_appserver_log_level flag.
Reference the new dev_appserver documentation.
To access uploaded files from a multipart/form-data POST request, the webapp2 documentation states that they're available in request.POST.

Related

Non ascii filename in blobstore (Google App Engine)

I am trying to upload some picture to Google App Engine using the Blobstore.
And some of the files contain non-ascii characters.
When I download these files, the filename for these downloaded file appeared to show the "key" in blobstore, rather than the original file name.
My site is http://wlhunaglearn.appspot.com/
I already add a save_as=blob_info.filename in my BlobstoreDownloadHandler , but it failed when the file name contains non-ascii characters.
Any suggestions?
Thanks in advance.
The following is my main.py file
# -*- encoding: utf-8 -*-
import os
import urllib
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
class MainHandler(webapp2.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload')
self.response.out.write('<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><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" multiple 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') # 'file' is file upload field in the form
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, save_as=blob_info.filename)
app = webapp2.WSGIApplication([('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler)],
debug=True)
Searching all the posts, I finally got a hint from an Answer to another Question
I figure out the correct way to display non-ascii file name is to
add a urllib.quote function to the last line of ServeHandler class
Therefore the ServeHandler class will be:
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, save_as=urllib.quote(blob_info.filename.encode('utf-8')))

GCS upload is realy slow from GAE

I have setup a simple python project on GAE, the user picks a file and it uploads into Google Cloud Storage. This all works fine, but I am getting an upload time of 10-11 seconds when I am uploading a 100kb file. How can I reduce this?
Extra info:
I have a 100Mbis upload speed and the result is the same with a 4kb image, the latency of the first post id about 6 seconds
import os
import urllib
import webapp2
from google.appengine.ext import blobstore
from google.appengine.ext.webapp import blobstore_handlers
class MainHandler(webapp2.RequestHandler):
def get(self):
upload_url = blobstore.create_upload_url('/upload', gs_bucket_name='bucket_name')
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') # 'file' is file upload field in the form
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)
app = webapp2.WSGIApplication([('/', MainHandler),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler)],
debug=True)

Why upload handler not match when using GAE blobstore

I just follow GAE's document (https://developers.google.com/appengine/docs/python/blobstore/#Python_Uploading_a_blob) to write upload handler to upload blobstore, when I select one file on computer and click Submit button on HTML page, it will show 'The url "/upload" does not match any handlers.'
Any comments is appreciated.
class MainPage(webapp2.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/html; charset=utf-8'
upload_url = blobstore.create_upload_url('/upload')
logging.info(upload_url)
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):
logging.info('Upload handler')
upload_files = self.get_uploads('file') # 'file' is file upload field in the form
blob_info = upload_files[0]
logging.info(upload_files)
self.redirect('/serve/%s' % blob_info.key())
class ServeHandler(blobstore_handlers.BlobstoreDownloadHandler):
def get(self, resource):
resource = str(urllib.unquote(resource))
logging.info(resource)
blob_info = blobstore.BlobInfo.get(resource)
self.send_blob(blob_info)
application = webapp2.WSGIApplication([
('/', MainPage),
('/upload', UploadHandler),
('/serve/([^/]+)?', ServeHandler),
], debug=True)
[Update1]
After I click submit button, I check dev-server Blobstore Viewer, I found the file has been uploaded there, however, my chrome browser still show 'The url "/upload" does not match any handlers.'. This is why?
I want to ask my question by self that maybe someone encounter similar issue as me.
After I change from
- url: /
script: AppWS.application
to
- url: (/.*)*
script: AppWS.application
everything is OK.

Storing a string from a textbox to the Google App Engine Datastore

Is it possible to create a textbox in HTML, type a string into it, click a "save" button, store that information onto a GAE datastore model and have the text stay displayed in the textbox and saved in the datastore?
The HTML is on a separate file, just rendered through my main.py file using
class MainPage(webapp.RequestHandler):
def get(self):
template_values = {}
path = os.path.join(os.path.dirname(__file__), 'index.html')
self.response.out.write(template.render(path, template_values))
What I tried for my problem is this:
class equipmentBox(db.Model):
equipCode = db.StringProperty()
class equipmentBoxGet(webapp.RequestHandler):
def post(self):
I think this will help, i have modified default guestbook app for you. Usual way of doing is having html files separately and using templates to render it. Here everything is just embedded into the controller itself
import cgi
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db
class EquipmentBox(db.Model):
equipCode = db.StringProperty()
class MainPage(webapp.RequestHandler):
def get(self):
self.response.out.write('<html><body>')
equips = db.GqlQuery("SELECT * FROM EquipmentBox")
for equip in equips:
self.response.out.write('<blockquote>%s</blockquote>' %
cgi.escape(equip.equipCode))
# Write the submission form and the footer of the page
self.response.out.write("""
<form action="/post" method="post">
<div><input type="text" name="equip_code" /></div>
<div><input type="submit" value="post equipcode"></div>
</form>
</body>
</html>""")
class EquipBox(webapp.RequestHandler):
def post(self):
equip = EquipmentBox()
equip.equipCode = self.request.get('equip_code')
equip.put()
self.redirect('/')
application = webapp.WSGIApplication(
[('/', MainPage),
('/post', EquipBox)],
debug=True)
def main():
run_wsgi_app(application)
if __name__ == "__main__":
main()
The best way to build this sort of interface, where the user "saves" data on the page without the page changing, is to use AJAX calls.
While a full explanation of how AJAX works is probably beyond the scope of an answer here, the basic idea is that you have a Javascript onclick event attached to your Save button, which sends the contents of your textbox via a POST request to the server. See the link above for a tutorial.

Uploading a HTML file to Google App Engine - getting 405

I'm trying to do a simple echo app using Python. I want to submit a file with a POST form and echo it back (an HTML file).
Here's the handlers section of the YAML I'm using:
handlers:
- url: /statics
static_dir: statics
- url: .*
script: main.py
It's basically the hello world example in main.py and I added a directory to host my static html form file. Here's the HTML in statics/test.html:
<form action="/" enctype="multipart/form-data" method="post">
<input type="file" name="bookmarks_file">
<input type="submit" value="Upload">
</form>
The handler looks like this:
#!/usr/bin/env python
from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
class MainHandler(webapp.RequestHandler):
def get(self):
self.response.headers['Content-Type'] = 'text/plain'
self.response.out.write(self.request.get('bookmarks_file'))
def main():
application = webapp.WSGIApplication([('/', MainHandler)],
debug=True)
util.run_wsgi_app(application)
if __name__ == '__main__':
main()
However, I'm getting an error 405 when posting the file. How come?
You are submitting your form with the POST method, but you implemented a get() handler instead of a post() handler. Changing def get(self): to def post(self): should fix the HTTP 405 error.

Categories