我是google appengine的新手。
我已将图像存储在blob字段中。我试图让图像显示错误。
下面我已经粘贴了我的代码和输出。
main.py
import cgi
import webapp2
from google.appengine.api import users
from google.appengine.ext.webapp.template \
import render
from os import path
from google.appengine.ext import db
from google.appengine.api import images
import urllib
import re
import datetime
class imgstore(db.Model):
name=db.StringProperty(multiline=True, default='')
image=db.BlobProperty()
class MainHandler(webapp2.RequestHandler):
def get(self):
moviequery=db.GqlQuery('SELECT * FROM imgstore')
context={
'list':moviequery
}
tmpl = path.join(path.dirname(__file__), 'static/html/index.html')
self.response.out.write(render(tmpl, context))
def post(self):
name1 =images.resize(self.request.get("file"), 32, 32)
formdata = db.Blob(name1)
insert = imgstore()
insert.name="name"
insert.image=formdata
insert.put()
routes=[
(r'/', MainHandler),
]
app = webapp2.WSGIApplication(routes=routes,debug=True)
的index.html
> <html>
> <head><title>test</title></head>
> <body>hello
> <form id="form" action="/" method="post" ENCTYPE="multipart/form-data">
> <input type="file" name="file" >
> <input type="submit" name="submit">
> </form>
> {% for lis in list%}
> <img src="{{lis.image}}">
> {% endfor %}
> </body>
> </html>
输出
Traceback (most recent call last):
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1536, in __call__
rv = self.handle_exception(request, response, e)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1530, in __call__
rv = self.router.dispatch(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1278, in default_dispatcher
return route.handler_adapter(request, response)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 1102, in __call__
return handler.dispatch()
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 572, in dispatch
return self.handle_exception(e, self.app.debug)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/webapp2/webapp2.py", line 570, in dispatch
return method(*args, **kwargs)
File "/Users/saravase/test/main.py", line 44, in get
self.response.out.write(render(tmpl, context))
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/template.py", line 92, in render
return t.render(Context(template_dict))
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/template.py", line 172, in wrap_render
return orig_render(context)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 173, in render
return self._render(context)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 167, in _render
return self.nodelist.render(context)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 794, in render
bits.append(self.render_node(node, context))
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 807, in render_node
return node.render(context)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/defaulttags.py", line 173, in render
nodelist.append(node.render(context))
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 847, in render
return _render_value_in_context(output, context)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/template/__init__.py", line 827, in _render_value_in_context
value = force_unicode(value)
File "/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/_internal/django/utils/encoding.py", line 88, in force_unicode
raise DjangoUnicodeDecodeError(s, *e.args)
DjangoUnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte. You passed in '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00 \x00\x00\x00\x14\x08\x06\x00\x00\x00\xec\x91?O\x00\x00\x066IDATx\x9c\xad\xd6i\x8c\x95W\x19\x07\xf0\xffs\xce}\xdf\xf7ns/\xb3\xdc;03\xcc\xc0\xb0\xcc\x1d\x8a\xb4\x99\xb2:\x05KS\xa8\xa4M\x00\x95\x8e\xd3\xfa\xc1%\xe9W5\xa9\xf1\x83\x89F\xe3\x17hP\x96\x84hCB\x14k\xc4b\x04\xaa\xb5j\xd0V\xa4\xd0\xa1(\x85P\x18(\xcc\xc2,\xf7\xce\x1d\xee\xdc}}\xcf\xf3\xf8\x81E\x88\xadv\xf1|?y~\xf9\xff\x9f\x9c\x1c\x12\x11\x00\x80\x08+aQJ+\x06\x88\x01\xa0\\\xae\xea\xb1\xe1+\xab*\xf9\xcc\xa2\xba\xc6\xd6\xe3\xed\xf3\xe7\x8d\x01 aV\x02\x81R\xda\xe0\x13\x1ebf\x05\x08\x88\x14\x03\x801\x8c\xc4\x8d\xe1\xee\x91\xc1\xb7\xb6M\\;\xf5\xb9Rvt)\x8c\xe8\x91\x1b\x95t\xe3\xdc\x15\xbf\xda\xf4t\xff\xee\x8eEK.\x03 \x11&\x11\xa1O\x02!\x11!\x01djrb\xee\x85\xb7^\xdf:6x\xaa_J#+,OI\xdb\xb6\x03\xed\xb1\x85\xd9\x15\x9fch|<I\xa9\x8c\xc7\x9d\xbd\xe0\x91\xa3\xab7\xf4m\xef\xfaT\xcf\x19\xa5\x08"\xa2DX)\xa5\xdd\x8f\x0c\x18\xba\xf4^\xec\x97\xfb^\xd8\x11\xf2\x8fo\xf0\xeb\x927P\xe7@\xdb>Q\x8a\x8cV\xae\xb2-V\x8e#\x10\xe3\nC\x99\xe4tE\xb3\xa9\x10\xa0\xc4\xd8\xb1\xe3]\xbd\xcfl_\xb1\xfa\x91\xe3Z+\x11\x11%\xccJie\x00\x92\x0f\x05\xb8\xfc\xee\xa5\r\x07\xf7>\xff\xa7\xdc\xf8$Z\xe6\xd4\xbb\xd19\x01j\x8e\xdaZ\x00@\x04\x86\x05\x95\xb2\x0b\xd75\xf0X\n\xa1:\r\xdb\xb1\xdcBA\xa9|6\xa7\xd2\x99<\x9cP\xe7\xe9\x07{\xb7m\x7f`\xe5\xe3\xaf8^\xdb\x88\x08\t\xb3VJ\x19\xd0\x7f\x87\x90\x88`\xaa4\xb8\xe3\xec\x89C\xdf\x1a8v\xb6\x96\x9d\x98\xb0ZZ\x03X\x1c\x8b\xc00\xa1RfX\xb6\x86\xe5\x01<\x1e\x8dR\xb9\x8aJ\xc5\xc0\xf1\x06\xe1x\xaaF\xab\x1a\x15KU\x8aON\x13\xac\xf9\xe7\x97\xac\xe9\xdb\xbe\xe6\xf1\'\x0e;^_\xf5\x0e\x84\x942\xf4\x01\x10\x12f\xb8\x02gd\xe4\xd8I\xedM<|\xfdb\xbav\xf27oX\xd5\\\x12\xdd\xb1F45\xcfB6\'0\xb5*|\xfe H\tr\xe9\x0cf\xd5\xdb(\x95\xca(\x96\x14\x0c+\xe3\xa8\x12\x88\\\x95L\xe6\xc9\x0e\xce\xbd\xb2\xacw\xeb\x0b=\x8fn~\xc9\xf1\x05K\x10!\x16\xd6D\xff\t!fVD\xc4\xc9\x1b\xc3\xb1k\xe7\xf7\xfc\xad\xe7\xb3]\x91\xa2;\xcf}\xe3\xc8\xdb\xfa\xc4\x91?\x92\xc3\x05,\x8e\xb5"\x10\xf2\x02b \x0cd\xf35\x84\xc3\x01dRi\x04\x82\x16\x08\x04f\x03\xcbr\rA!\x93.\xa8\xa9D\x96\xac@\xf3\xf0\xb2\xb5\x9f\xff\xf1\xea\x8d\xdb\x0e\xd4\x85g\xe5\x00!\xe6\xfb!$"\x10\x11ED<=v}\xf1\xd4\xd0\xfe\x83\xb3c\xee\xca\x86\xc8g\xccT\x9a\xf0\xfb\x9f\xbd\xa2/\xfe\xfdm\xb4D\x1dD"Ax}!T\xdd*\xaa\x15\x83B\xae\x86`\xd0F\xa4\xb9\x1e\xf9\xecMT\xaa.&\xe3%h\xcba\xadXl\x95W\xe5R\x91*\xdc4\xb1\xf0\xe1/\xec\xd9\xb8\xf5\x8b/\xce\x8a6\xcc\x88\x08\xdd\x99I\xff~\x88D\x11\x91T\xcbU\x15\xbfz\xec\xeb.\xff\xf9\xfb\xd1E\x9d\xc1\xa0\xbf\xc7\x0c\r\x0f\xd1\xb1\xfd\xaf\xaa\xf3\xa7\xaf`v\xc4\x8bh4\x00\xcbr\xe0\xf5Y "d3\x15\x14+\x04\xad\x05\xe1\x90\rK\x0b|^A6W\xe1t\xc6p\xb1lt\xb1X\xa6j-\x90\\\xbf\xb9o\xcf\xba\xa7\x9e\xdd\xd7\xd0T\x9f\x02\x84\xee\x02\xee" \x04Rf&>:/9rp\x97\xbfqt\xf3\x9c\xce\x1e\xd1j\x8e9w\xfa\xac>\xfc\xe2_(~#\x89\xeeX\x14A\xbf\x03Q6\xf2\x05\x83P\x90\xe1\xf1\x10<\x9a\x90\xcd\xd6\x90H\xe6\x90\xc9\xb9\xc8\x97\x04\x8e\xad9\x1a\xf1K\xd0g\xd4\xe8p\x9c\xaa\xd2\x9cZ\xf7d\xff\x0f\xb7|\xe5\xb9\xbd\xf7\x01n3n\xc7\xa3\xd8\xb8\x90\xf8\xb5\xd7\xb7\xe6S/\xef\x8a,\xd0\xed\r\xd1\x1e6F\xc9_\x8f\x9e\xd6\x87\x0f\x9cB\xb9P\xc4\xc2\x05\x8dhj\x0c\xa2\\)#\x9d1\x98\x9e\xa9\xa0P\xac\xc2\xb1=\xf0\xfb-\xd4\x05m\x84\x02\x1a\xa5R\x05#\xe3y\xa9Q\xc04DZt]\x98\xe8\xab\xdf\xfc\xc1\x86\xf7\x01\xdcI\x83\x15\x01\x04R\xa6\x90\xc9\xd4%\xaf\xff\xfa;\xa0\x13\xdfhZ\xd0\xe6\x04\xeb\x16\x98\xd4t\x86\x0e\xfd\xf4\xa4:z\xe8\x9f\xd0\x9a\xd1\xda\x12\x023A\x88\x00\x114\xd4\xfb0\xbb\xc9\x01\xc4 q\xb3\x8c\xa1q\x17\xb67\x8c\x9e5\x8by\xd5\xc6v\xb5p\xe9\x923\x91\xe0\x965\x1f\x08\xb8\x07\xa2om,q:~56s\xe3\xe7?\xb2}W6E\x17v\x88\xe5\x8d\xf2\xe8\xa5\xb4:\xb0\xf7,]\xf8\xc7\x08b]MplA\xa1PF8\xe4\xc1\xf4L\x19\xc94\x83t\x1d:\x16\xb7\xe0\xb1M\xed\xe8^\x1a2\\\xcdh+\xd0\xfftSt\xf9\xcb\xff\x13p{7\x08\xb8S\x8b\xc8\xf8\xe5\xe3[\xf2\x93\x07v\x86\xc3\xc9\xce\xe6\xaen\xf6\x84\xda\xe4\xd4kc\xfa\xc8/."\x9e\x98\x81\xd7o!\x9f\xad@\xd96b=\xf3\xf1\xe9\xc7\xda\xd0\xd5m\xc3\xaa\x95j\xf1+\xa3\xd6t\xb2\xf5\xc4\xba\xfe\xdd\xeb\xb4\x87\xe8C\x01\xee\xad\x05\x00\x11)\x93\xcf\xe6\xfcc\xe7\x0e>_\x9a8\xfc\xed\xb9\xb1\xa0\xbf\xe9\xa1\xe5&\x9d\x04\xbd\xf9\x87\x1959\xec"S\xcb\xe0\xa1G\xdb\xd0\xd5\xe9\xc2\xaa\xa487]\xe4\xe1\x8b\xe3\x9e\xab\x97s\xc5\xb5\xcf\xfcd\xfd\x03+V\x0e\x08\xb3\xfaH\x80\xf7\xabej\xf4Z\xe7\xe8\xc0\xae=\xb3\x02\xef<\xd9\xfe`\x07\xdb\x8d\xcd29\xdd\xa1\xb57\x07\xdbMq\xe2\x9d\xabr3\x91UC\x83q\xaa\xd0\xa23k\xb7}\xf7\xb9E\xcb\x96\x9f\x13aE\xa4\xf8c\x01n!\x84\x00\xd6D\xda\x18\x86\x8c\x9c\xfdm\xdf\xd4\x85}\xbb[Z3\xcds\xd7?\xcb\x89\xa1Q\x0c\x0f\x0c\xd0{\xef&\xa8(-C\xb1\xde\xaf}o\xd5\xc6\xbe\x97\x1c\xc7faV\xa4n\xfd?>6\xe0\x9e4\xee\xd6\x92\x99N6^xm\xe7\x0e\xe2s_N\xa5\xf2*1\xa9G\xda\x96\xf5\xed\xec}\xeaK\xfb\xeb\xc2\xa1\x92\x08k\x08\xe4\xce\xf0\xff\x0b\xe0.\x84\x8d&\xa5\x98\x85d\xf0\xcc\x9b\xbd\xe9\xd4d\xfb\x92U\xeb\x7f\x17\xaeo\xc8AD\xf1\xad\xc8]"\xba\xef\xde\xbf\x00E\x15c\xc0\xf90\xc3\xa2\x00\x00\x00\x00IEND\xaeB`\x82' (<class 'google.appengine.api.datastore_types.Blob'>)
请指导我如何进一步。
答案 0 :(得分:1)
你需要做两件事。首先,您需要更改HTML,以使src
标记的img
包含应用程序提供的URL。其次,您需要实现一个处理程序来为URL提供服务。
假设您的应用程序将使用以下网址提供存储的图片:/image/15
其中15是id
实体的imgstore
。您需要添加路线:
routes=[
(r'/image/(\d+)', ImageHandler),
(r'/', MainHandler),
]
app = webapp2.WSGIApplication(routes=routes,debug=True)
然后你需要添加一个新的RequestHandler类:
class ImageHandler(webapp2.RequestHandler):
def get(self, image_id):
requestedImage = imgstore.get_by_id(int(image_id))
if requestedImage is not None:
self.response.out.write(requestedImage.image)
else:
# return a default image when we can't located the
# one that was requested?
新路由包含一个数字捕获 - (\d+)
- 将作为参数传递给请求处理程序。然后我们可以使用该id直接从数据存储区获取图像实体;它比使用查询要快得多。
那么,我们从哪里获取id?数据存储区中的每个实体都会自动分配一个整数id,除非您在存储它时为其指定ID或名称。
您需要做的最后一件事是提供一种简单的方法来将将您的图像提供服务的URL嵌入到包含img
标记的模板中。在imgstore类中添加一个方法:
class imgstore(db.Model):
name=db.StringProperty(multiline=True, default='')
image=db.BlobProperty()
def url_for(self):
return "/image/%d" % self.id
现在您可以更改模板以使用新方法:
<img src="{{lis.url_for}}">