Displaying Blob Images in Python (App Engine)

2019-01-26 13:26发布

问题:

I am unable to get the image to display on the page. I can store it just fine.

These are the handlers:

class disp_image(webapp.RequestHandler):
    def get(self):
        key = self.request.get('key')
        image = Images.get(key)
        if image:
            self.response.headers['Content-Type'] = "image/png"
            return self.response.out.write(images.image)
        else:
            self.response.headers['Content-Type'] = "image/png"
            return self.response.out.write("/static/unknown.gif")

class Profile(MainHandler):
    def get(self):      
        if self.user:
            self.render('profile.html', username = self.user.name, email = self.user.email, first_name = self.user.first_name, last_name = self.user.last_name, country = self.user.country, prov_state = self.user.prov_state, city_town = self.user.city_town)
        else:
            self.redirect('/register')

class Change_Profile_Image(MainHandler):
    def get(self):
        if self.user:
            self.render('change_profile_image.html', username = self.user.name, firstname=self.user.first_name)
        else:
            self.render('change_profile_image.html')

    def post(self):
        images = Images()
        imageupl = self.request.get('img')
        images.image = db.Blob(imageupl)
        images.put()
        self.redirect('/profile')

db stuff is a follows:

class Images(db.Model):
    image = db.BlobProperty()

class User(db.Model):
    name = db.StringProperty(required=True)
    pw_hash = db.StringProperty(required=True)
    email = db.StringProperty(required=True)
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    country = db.StringProperty()
    prov_state = db.StringProperty()
    city_town= db.StringProperty()
    clan= db.StringProperty()
    handle= db.StringProperty()

The form:

<form enctype="multipart/form-data" method="post">
       <input type="file" name="img" />
</form>

My template substitution bit of code:

<img src="/disp?key={{image}}" /></img>

回答1:

For one, I think you're mixing up the image key and the image binary data.

The Template

You should be writing the image key (string) to your template:

 <img src="/disp?key={{image_key}}" />

i.e. your final html should look like the following if you just pass image.key() to your template:

 <img src="/disp?key=AC3CK3333KCCK2K213" />

You can think of it as a two step process. You render your template. The user browser renders the html and does a get to your image handler. The image handler then sends the binary data.

(Btw, I was under the impression you close your html tags with either <img ... /> or <img ...></img>, not both <img .../></img>)

Image Handler

In your image handler, disp_image, you should be returning the binary data of the image. It looks like you first condition is okay, but I think your else condition will just return the text "/static/unknown.gif" and not the actual binary data of the gif file.

    else:
        self.response.headers['Content-Type'] = "image/png"
        return self.response.out.write("/static/unknown.gif")

You should either store unknown.gif in your datastore and refer to it by key or you should be writing the "/static/unknown.gif" url to your template in lieu of "/disp?key=..."

Lastly, the simplest way to test whether your image handler is working is when you plug in <domain>/disp?key=... into your browser URL bar, it should load the desired image.



回答2:

You do not have to serve images yourself. Google can do the job with Google High-Performance Image Serving for free! See: https://developers.google.com/appengine/docs/python/images/functions get_serving_url(blob_key, size=None, crop=False, secure_url=None) Where you only have to get the serving url once and save it for use in your HTML templates in your Images model class.



回答3:

I am not sure, but I think you should not return from the get method at the disp_image class.

class disp_image(webapp.RequestHandler):
    def get(self):
        key = self.request.get('key')
        image = Images.get(key)
        if image:
            self.response.headers['Content-Type'] = "image/png"
            self.response.out.write(images.image)
        else:
            self.response.headers['Content-Type'] = "image/png"
            self.response.out.write("/static/unknown.gif")

Could you explain where is the template rendering called from? Where are you passing the image attribute?