0

I am trying to store an image in the redis and retrieve it and send it to an HTML template. I am able to cache the image but I dunno how to retrieve the image back and send it to the HTML template. This is the part of my code which does caching and retrieving.

from urllib2 import Request, urlopen
import json
import redis
import urlparse
import os
from StringIO import StringIO
import requests
from PIL import Image
from flask import send_file

REDIS_URL = urlparse.urlparse(os.environ.get('REDISCLOUD_URL', 'redis://:@localhost:6379/'))
r = redis.StrictRedis(
            host=REDIS_URL.hostname, port=REDIS_URL.port,
            password=REDIS_URL.password)

class MovieInfo(object):
    def __init__(self, movie):
        self.movie_name = movie.replace(" ", "+")

    def get_movie_info(self):
        url = 'http://www.omdbapi.com/?t=' + self.movie_name + '&y=&plot=short&r=json'
        result = Request(url)
        response = urlopen(result)
        infoFromJson = json.loads(response.read())
        self._cache_image(infoFromJson)
        return infoFromJson

    def _cache_image(self, infoFromJson):
        key = "{}".format(infoFromJson['Title'])
        # Open redis.
        cached = r.get(key)
        if not cached:
            response = requests.get(infoFromJson['Poster'])
            image = Image.open(StringIO(response.content))
            r.setex(key, (60*60*5), image)
            return True


    def get_image(self, key):
        cached = r.get(key)
        if cached:
           image = StringIO(cached)
           image.seek(0)
           return send_file(image, mimetype='image/jpg')

if __name__ == '__main__':
    M = MovieInfo("Furious 7")
    M.get_movie_info()
    M.get_image("Furious 7")

Any help on the retrieving part would be helpful. Also whats the best way to send the image file from a cache to a HTML template in Flask.

Eric
  • 2,636
  • 21
  • 25
Arman
  • 194
  • 9

1 Answers1

1

What you saved in Redis is a string, Something likes:'<PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=300x475 at 0x4874090>'.

response.content is rawData . use Image.frombytes() to get Image object.

Check here : Doc

You can't create nested structures in Redis, meaning you can't (for example) store a native redis list inside a native redis hash-map.

If you really need nested structures, you might want to just store a JSON-blob (or something similar) instead. Another option is to store an "id"/key to a different redis object as the value of the map key, but that requires multiple calls to the server to get the full object.

Try this:

response = requests.get(infoFromJson['Poster'])
# Create a string buffer then set it raw data in redis.
output = StringIO(response.content)
r.setex(key, (60*60*5), output.getvalue())
output.close()

see: how-to-store-a-complex-object-in-redis-using-redis-py

Community
  • 1
  • 1
SimonShyu
  • 95
  • 8
  • Sorry, am new to this. Am not able to get it. can you point me in my code where I should change it. – Arman Feb 22 '16 at 21:38
  • Hi I modified the caching part with your suggestion, but what I get is RuntimeError('working outside of application context') RuntimeError: working outside of application context – Arman Feb 23 '16 at 08:11
  • I found this, [RuntimeError: working outside of application context](http://stackoverflow.com/questions/31444036/runtimeerror-working-outside-of-application-context) – SimonShyu Feb 23 '16 at 08:35
  • I fixed the runtime issue. This is my project repo https://github.com/arunraman/Code-Katas/tree/master/MovieLocator I am trying to get the image file from redis and push it to the HTML template, but the image_file is not coming up correctly. I am new to flask. Any help is appreciated. – Arman Feb 24 '16 at 07:42
  • I see `` in your template.The **src** attribute specifies the URL (web address) of the image.So, `get_image()` return `infoFromJson['Poster']` will be ok. – SimonShyu Feb 25 '16 at 01:34