1

我是谷歌应用引擎的新手。

我已将图像存储在 blob 字段中。我正在尝试获取显示错误的图像。

下面我粘贴了我的代码和输出。

主文件

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)

索引.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'>)

请指导我如何进一步进行。

4

1 回答 1

1

你需要做两件事。首先,您需要更改您的 HTML,以便src标记的img包含由您的应用程序提供的 URL。其次,您需要实现一个处理程序来为 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}}">
于 2012-07-25T14:31:34.713 回答