librelist archives

« back to archive

How can I display an image loaded from a database?

How can I display an image loaded from a database?

From:
Malphas Wats
Date:
2012-05-18 @ 09:16
Hi,

  I'm working on a new project which has a simple profile page. I want
to store the user's avatar in the database and supply it to a template
as if it's an image from a file? I've got as far as loading the image
binary back from the database, what do I do with it now?!

Thank you!

Re: [flask] How can I display an image loaded from a database?

From:
Simon Sapin
Date:
2012-05-18 @ 10:41
Le 18/05/2012 11:16, Malphas Wats a écrit :
> Hi,
>
>    I'm working on a new project which has a simple profile page. I want
> to store the user's avatar in the database and supply it to a template
> as if it's an image from a file? I've got as far as loading the image
> binary back from the database, what do I do with it now?!


As said by others you should *consider* having "real" files in the 
filesystem instead of binary blobs in the database. But there are also 
valid reasons to go the DB way, especially if the images are small.

If you want each image to have its own URL add a view and URL rule like 
any other, and return the byte string with the right MIME type:

from flask import Response

@app.route('/avatar/<int:user_id>.jpg')
def avatar(user_id):
     jpeg_byte_string = get_avatar_or_404(user_id)
     return Response(png_byte_string, mime_type='image/jpeg')


In the template:

<img src="{{ url_for('avatar', user_id=42) }}">

-- 
Simon Sapin

Re: [flask] How can I display an image loaded from a database?

From:
Sebastien Estienne
Date:
2012-05-18 @ 10:48
I also think, storing the database is not always a bad idea.

But you must have a cache layer (akamai/edgecast) or your own server
(varnish/squid).

And also make sure to have proper HTTP headers, the example from Simon
is missing the expires / ifmodified / etags headers that would allow
the caching to works well.

If you have the headers right and use a cache layer, it should work well!

Sebastien Estienne


On Fri, May 18, 2012 at 12:41 PM, Simon Sapin <simon.sapin@exyr.org> wrote:
> Le 18/05/2012 11:16, Malphas Wats a écrit :
>> Hi,
>>
>>    I'm working on a new project which has a simple profile page. I want
>> to store the user's avatar in the database and supply it to a template
>> as if it's an image from a file? I've got as far as loading the image
>> binary back from the database, what do I do with it now?!
>
>
> As said by others you should *consider* having "real" files in the
> filesystem instead of binary blobs in the database. But there are also
> valid reasons to go the DB way, especially if the images are small.
>
> If you want each image to have its own URL add a view and URL rule like
> any other, and return the byte string with the right MIME type:
>
> from flask import Response
>
> @app.route('/avatar/<int:user_id>.jpg')
> def avatar(user_id):
>     jpeg_byte_string = get_avatar_or_404(user_id)
>     return Response(png_byte_string, mime_type='image/jpeg')
>
>
> In the template:
>
> <img src="{{ url_for('avatar', user_id=42) }}">
>
> --
> Simon Sapin

Re: [flask] How can I display an image loaded from a database?

From:
Anthony Ford
Date:
2012-05-18 @ 12:49
Out of curiosity, had you considered using an external service, such as
gravatar ( http://en.gravatar.com/ ).

There's even a flask extension for it:
http://packages.python.org/Flask-Gravatar/

Anthony Ford,
ford.anthonyj@gmail.com,
Research Assistant,
Center for Advanced Radio Astronomy,
University of Texas - Brownsville
On May 18, 2012 5:49 AM, "Sebastien Estienne" <sebastien.estienne@gmail.com>
wrote:

> I also think, storing the database is not always a bad idea.
>
> But you must have a cache layer (akamai/edgecast) or your own server
> (varnish/squid).
>
> And also make sure to have proper HTTP headers, the example from Simon
> is missing the expires / ifmodified / etags headers that would allow
> the caching to works well.
>
> If you have the headers right and use a cache layer, it should work well!
>
> Sebastien Estienne
>
>
> On Fri, May 18, 2012 at 12:41 PM, Simon Sapin <simon.sapin@exyr.org>
> wrote:
> > Le 18/05/2012 11:16, Malphas Wats a écrit :
> >> Hi,
> >>
> >>    I'm working on a new project which has a simple profile page. I want
> >> to store the user's avatar in the database and supply it to a template
> >> as if it's an image from a file? I've got as far as loading the image
> >> binary back from the database, what do I do with it now?!
> >
> >
> > As said by others you should *consider* having "real" files in the
> > filesystem instead of binary blobs in the database. But there are also
> > valid reasons to go the DB way, especially if the images are small.
> >
> > If you want each image to have its own URL add a view and URL rule like
> > any other, and return the byte string with the right MIME type:
> >
> > from flask import Response
> >
> > @app.route('/avatar/<int:user_id>.jpg')
> > def avatar(user_id):
> >     jpeg_byte_string = get_avatar_or_404(user_id)
> >     return Response(png_byte_string, mime_type='image/jpeg')
> >
> >
> > In the template:
> >
> > <img src="{{ url_for('avatar', user_id=42) }}">
> >
> > --
> > Simon Sapin
>

Re: [flask] How can I display an image loaded from a database?

From:
Malphas Wats
Date:
2012-05-18 @ 14:06
On Fri, May 18, 2012 at 1:49 PM, Anthony Ford <ford.anthonyj@gmail.com> wrote:
> Out of curiosity, had you considered using an external service, such as
> gravatar ( http://en.gravatar.com/ ).
>
> There's even a flask extension for it:
> http://packages.python.org/Flask-Gravatar/
>
> Anthony Ford,
> ford.anthonyj@gmail.com,
> Research Assistant,
> Center for Advanced Radio Astronomy,
> University of Texas - Brownsville


Thanks Anthony, I use Gravatar a fair bit in other projects but it
wouldn't quite suit this application as it needs to be brain-dead
simple (it's for the school I work at). There will also be a file
upload feature, so I was planning ahead for that too :)

I think on balance, I'll look at setting up a separate domain to serve
static files from and keep all the application stuff separate.

Lots of good answers though, thank you all for your help. I think the
canonical answer to my question, leaving aside all of the "is this
actually the best option" stuff would be Simon's:

from flask import Response

@app.route('/avatar/<int:user_id>.jpg')
def avatar(user_id):
    jpeg_byte_string = get_avatar_or_404(user_id)
    return Response(png_byte_string, mime_type='image/jpeg')

That's how you do it, whether or not you should is a whole other thing :)

Re: [flask] How can I display an image loaded from a database?

From:
Ishbir Singh
Date:
2012-05-18 @ 09:45
Hey,

You could encode the binary into base64 and then use Data URI scheme to
display it. Here is a pointer:  http://en.wikipedia.org/wiki/Data_URI_scheme

On 18 May 2012 14:46, Malphas Wats <malphas@subdimension.co.uk> wrote:

> Hi,
>
>  I'm working on a new project which has a simple profile page. I want
> to store the user's avatar in the database and supply it to a template
> as if it's an image from a file? I've got as far as loading the image
> binary back from the database, what do I do with it now?!
>
> Thank you!
>



-- 
Regards,
Ishbir Singh

Re: [flask] How can I display an image loaded from a database?

From:
Sebastien Estienne
Date:
2012-05-18 @ 09:45
You must have a route in your app to the avatar image eg:
/user/<user_id>/avatar.jpg
and when this route is access, you SELECT the binary data and return
it as the content of the response with the proper HTTP headers
(content type, etc).

But it's not highly effective to do this, except if you add a layer of
cache in front of your webapp like varnish.

Sebastien Estienne


On Fri, May 18, 2012 at 11:16 AM, Malphas Wats
<malphas@subdimension.co.uk> wrote:
> Hi,
>
>  I'm working on a new project which has a simple profile page. I want
> to store the user's avatar in the database and supply it to a template
> as if it's an image from a file? I've got as far as loading the image
> binary back from the database, what do I do with it now?!
>
> Thank you!

Re: [flask] How can I display an image loaded from a database?

From:
pronoyc@gmail.com
Date:
2012-05-18 @ 09:39
I think I was stuck with the same problem and Armin advised that instead of
putting binary data in the database, you can upload the file to the static
folder and store it's path in the database. It is much more convenient. You
can checkout Flask-uploads for this kind of thing.

Hope that helps.

On Fri, May 18, 2012 at 2:46 PM, Malphas Wats <malphas@subdimension.co.uk>wrote:

> Hi,
>
>  I'm working on a new project which has a simple profile page. I want
> to store the user's avatar in the database and supply it to a template
> as if it's an image from a file? I've got as far as loading the image
> binary back from the database, what do I do with it now?!
>
> Thank you!
>



-- 
Regards,

Pronoy Chopra
http://blog.pronoy.in <http://www.pronoy.in/about>/
http://www.twitter.com/pronoyc

Re: [flask] How can I display an image loaded from a database?

From:
Sebastien Estienne
Date:
2012-05-18 @ 09:53
On Fri, May 18, 2012 at 11:39 AM, pronoyc@gmail.com <pronoyc@gmail.com> wrote:
> I think I was stuck with the same problem and Armin advised that instead of
> putting binary data in the database, you can upload the file to the static
> folder and store it's path in the database. It is much more convenient. You
> can checkout Flask-uploads for this kind of thing.

You don't even need to store the path in the DB.
eg: store in /data/avatars/$USER_ID.jpeg

you can generate the path to the image only knowing the SUSER_ID

If you can have a lot of images, hash the path:
eg: if USER_ID is numeric: 12345
tag the 2 last digits and store like this: /data/avatars/5/4/12345.jpeg

Re: [flask] How can I display an image loaded from a database?

From:
Malphas Wats
Date:
2012-05-18 @ 10:15
On Fri, May 18, 2012 at 10:53 AM, Sebastien Estienne
<sebastien.estienne@gmail.com> wrote:
> On Fri, May 18, 2012 at 11:39 AM, pronoyc@gmail.com <pronoyc@gmail.com> wrote:
>> I think I was stuck with the same problem and Armin advised that instead of
>> putting binary data in the database, you can upload the file to the static
>> folder and store it's path in the database. It is much more convenient. You
>> can checkout Flask-uploads for this kind of thing.
>
> You don't even need to store the path in the DB.
> eg: store in /data/avatars/$USER_ID.jpeg
>
> you can generate the path to the image only knowing the SUSER_ID
>
> If you can have a lot of images, hash the path:
> eg: if USER_ID is numeric: 12345
> tag the 2 last digits and store like this: /data/avatars/5/4/12345.jpeg

Thanks Sebastien, I suppose you're right, ultimately the filesystem is
going to be the best place to store files!

I think my problem is I'm still new to Flask and I'm getting tied up
with the routing concept. I've noticed a few places in the Flask Docs
where it says "You're better off letting your webserver handle
requests for static files", which is great, but I can't quite work out
how to stop Flask from trying to serve the files.

If for example, I did as you suggest here, and create a /data
directory and put all the files in there, how do I stop Flask from
trying to serve the file and just let the webserver do it? Or would I
just always have to put them everywhere as url_for('data',
filename='avatars/12345.jpeg') (which I just tried and got a
BuildError: ('data', {'filename': 'defaultAvatar.png'}, None).

I'm comfortable with routing urls to methods, that makes sense, but
I'm struggling with the other stuff. I'm relearning from PHP and
apache RewriteRules :(

Re: [flask] How can I display an image loaded from a database?

From:
Sebastien Estienne
Date:
2012-05-18 @ 10:43
I'm using nginx + gunicorn for running my flask apps

So i can help you with this, but it should be similar for apache

The basic idea is to store all your static content (css, js, jpeg,
etc) in the same hierarchy on the filesystem and the webapp.
eg: http://domain.com/static/* will map to
/data/webapp/domain.com/static/ folder

so in you webserver configuration you have a rule that match the
/static/* and serve the content of  /data/webapp/domain.com/static/

if this rule is not matched, then you have another rule to proxy to your webapp

example from my nginx conf:

    location ~ '/static/(?:_[a-z0-9]+_/)?(.+)$' {
        expires max;
        alias /data/webapps/myapp/static/$1;
    }

    location / {
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;
        proxy_pass http://myapp;
    }

and the proxy_pass directive link to this upstream:

upstream myapp {
    server 127.0.0.1:8100 fail_timeout=0;
}

gunicorn is listening on localhost port 8100 serving my Flask app

Sebastien Estienne


On Fri, May 18, 2012 at 12:15 PM, Malphas Wats
<malphas@subdimension.co.uk> wrote:
> On Fri, May 18, 2012 at 10:53 AM, Sebastien Estienne
> <sebastien.estienne@gmail.com> wrote:
>> On Fri, May 18, 2012 at 11:39 AM, pronoyc@gmail.com <pronoyc@gmail.com> wrote:
>>> I think I was stuck with the same problem and Armin advised that instead of
>>> putting binary data in the database, you can upload the file to the static
>>> folder and store it's path in the database. It is much more convenient. You
>>> can checkout Flask-uploads for this kind of thing.
>>
>> You don't even need to store the path in the DB.
>> eg: store in /data/avatars/$USER_ID.jpeg
>>
>> you can generate the path to the image only knowing the SUSER_ID
>>
>> If you can have a lot of images, hash the path:
>> eg: if USER_ID is numeric: 12345
>> tag the 2 last digits and store like this: /data/avatars/5/4/12345.jpeg
>
> Thanks Sebastien, I suppose you're right, ultimately the filesystem is
> going to be the best place to store files!
>
> I think my problem is I'm still new to Flask and I'm getting tied up
> with the routing concept. I've noticed a few places in the Flask Docs
> where it says "You're better off letting your webserver handle
> requests for static files", which is great, but I can't quite work out
> how to stop Flask from trying to serve the files.
>
> If for example, I did as you suggest here, and create a /data
> directory and put all the files in there, how do I stop Flask from
> trying to serve the file and just let the webserver do it? Or would I
> just always have to put them everywhere as url_for('data',
> filename='avatars/12345.jpeg') (which I just tried and got a
> BuildError: ('data', {'filename': 'defaultAvatar.png'}, None).
>
> I'm comfortable with routing urls to methods, that makes sense, but
> I'm struggling with the other stuff. I'm relearning from PHP and
> apache RewriteRules :(

Re: [flask] How can I display an image loaded from a database?

From:
pronoyc@gmail.com
Date:
2012-05-18 @ 10:22
>
> If for example, I did as you suggest here, and create a /data
> directory and put all the files in there, how do I stop Flask from
> trying to serve the file and just let the webserver do it? Or would I
> just always have to put them everywhere as url_for('data',
> filename='avatars/12345.jpeg') (which I just tried and got a
> BuildError: ('data', {'filename': 'defaultAvatar.png'}, None).
>

I may be wrong, but I think it works only with static.

{{ url_for('static', filename="data/avatars/foo.jpg") }}

where data is in the static folder
-- 
Regards,

Pronoy Chopra
http://blog.pronoy.in <http://www.pronoy.in/about>/
http://www.twitter.com/pronoyc

Re: [flask] How can I display an image loaded from a database?

From:
Malphas Wats
Date:
2012-05-18 @ 09:48
> On Fri, May 18, 2012 at 2:46 PM, Malphas Wats <malphas@subdimension.co.uk>
> wrote:
>>
>> Hi,
>>
>>  I'm working on a new project which has a simple profile page. I want
>> to store the user's avatar in the database and supply it to a template
>> as if it's an image from a file? I've got as far as loading the image
>> binary back from the database, what do I do with it now?!
>>
>> Thank you!

On Fri, May 18, 2012 at 10:39 AM, pronoyc@gmail.com <pronoyc@gmail.com> wrote:
> I think I was stuck with the same problem and Armin advised that instead of
> putting binary data in the database, you can upload the file to the static
> folder and store it's path in the database. It is much more convenient. You
> can checkout Flask-uploads for this kind of thing.
>
> Hope that helps.
> --
> Regards,
>
> Pronoy Chopra
> http://blog.pronoy.in/
> http://www.twitter.com/pronoyc
>

Thanks Pronoy, I had considered that and may well have to fall back to
it, however, in past projects, splitting the database and filestore
has caused me some major problems with keeping backups in sync (and
doing backups at all once things got big and unruly, I wanted to keep
it easy and just dump the database out every now and then!)