Is it sensible to generate images on the fly/use a base64 string as image source?

65 views
Skip to first unread message

Spokes

unread,
Oct 20, 2014, 7:51:40 AM10/20/14
to
For reasons of which I'm not totally sure, I was unable to use web2py's download function with a particular table's upload field. Consequently, I hacked my way around it by doing something like this:

def return_image_as_string(db, table_name, field_name, image_name):
   
import base64
    _
, stream = db[table_name][field_name].retrieve(image_name)
   
return 'data:image/png;base64,' + base64.b64encode(stream.read())

def myfunc():
    img
= IMG(..., _src = return_image_as_string(...))
   
...

Does it make sense to do this from the point of view of efficiency, security, functionality (i.e. will it work on all browsers?), etc...? If the idea is fundamentally sound, are there better ways of doing it than the above?

Leonel Câmara

unread,
Oct 20, 2014, 8:13:49 AM10/20/14
to web...@googlegroups.com
This is pretty inefficient, I still think your original code was failing due to the table not being defined. Specifically response.download does this:

        items = re.compile('(?P<table>.*?)\.(?P<field>.*?)\..*').match(name)
       
if not items:
           
raise HTTP(404)
       
(t, f) = (items.group('table'), items.group('field'))
       
try:
            field
= db[t][f]
       
except AttributeError:
           
raise HTTP(404)


I think your 404 is this last one.

If you want, you could make a minimal application that reproduces your problem, post it here, and I'll fix it.

Spokes

unread,
Oct 20, 2014, 9:12:35 AM10/20/14
to
I still think your original code was failing due to the table not being defined

I put a print statement in the 'download' function to check that the db instance being passed to that function contains the required table, and it did seem to confirm that the table was there. Specifically, I did this:

def download():
   
print "\ndb.tables:", db.tables
   
return response.download(request,db)

Perhaps you're right about the source of the problem, but I'm a bit confused as to how the download function can see the table, and response.download does not.

I'll see if I can reproduce the issue in a minimal program. Thanks!


Message has been deleted

Leonel Câmara

unread,
Oct 20, 2014, 11:11:33 AM10/20/14
to web...@googlegroups.com
Ok you need to fix 2 things in your app, one of them shows I was right about the table definition problem:

First, in create_image() change:

image = IMG(_src = URL('default', 'download', record.user_image),  _style = 'height:200px;width:200px')

Into this:

image = IMG(_src = URL('default', 'download', args=record.user_image),  _style = 'height:200px;width:200px')


Then, you also need to define the table in your models or in the download controller, for it to work correctly. One way to do it is to call your User_Image(db = db, auth_signature = auth.signature) somewhere in your models or even in your download controller.

def download():
   
from user_custom import User_Image
    image_inst
= User_Image(db = db, auth_signature = auth.signature)    
   
return response.download(request,db)


Doing both these changes solved the problem.

By the way, I wouldn't have the User_Image class at all, since it's only defining the table, it serves no purpose, you may as well just define the table in your models and be done with it (which would result in simpler code all around).

Spokes

unread,
Oct 20, 2014, 11:38:37 AM10/20/14
to
Indeed, you're right - the combination of the two changes solved the problem. I thought that I had tried this previously, but perhaps I had tried one or the other change, without doing both. Thank you!

Still, isn't it possible to pretty much do away with modules without compromising functionality? It seems that Bruno Rocha did this with his Movuca app, and I thought I was doing something comparable.


By the way, I wouldn't have the User_Image class at all, since it's only defining the table, it serves no purpose

There's a lot more to it in the actual app, which justifies the module. This was just an abstracted example for the purpose of resolving this error issue. Also, the documentation, if I remember correctly, recommends moving all the model stuff to modules to promote efficiency, so I try to go along with that advice.

Leonel Câmara

unread,
Oct 20, 2014, 12:23:01 PM10/20/14
to web...@googlegroups.com
It isn't as necessary as it used to be to move models into modules because of lazy tables and the fact that you can run models conditionally now.

Either way I think that's usually a premature optimization.

Spokes

unread,
Oct 20, 2014, 12:42:47 PM10/20/14
to web...@googlegroups.com
Thanks - will keep this in mind.
Reply all
Reply to author
Forward
0 new messages