Problem Solution Discussion Retrieving Images or Other Binary Data

17.8 Retrieving Images or Other Binary Data

17.8.1 Problem

Okay, you can st ore im ages or ot her binary dat a values in your dat abase, using t he t echniques discussed in Recipe 17.7 . How do you get t hem back out ?

17.8.2 Solution

You need not hing m ore t han a SELECT st at em ent . Of course, what you do wit h t he inform at ion aft er you ret rieve it m ight be a lit t le m ore involved.

17.8.3 Discussion

As described in Recipe 17.7 , it s difficult t o issue a st at em ent m anually t hat st ores a lit eral im age value. However, t here is no problem at all ent ering a query t hat ret rieves an im age: mysql SELECT FROM image WHERE id = 1; But binary inform at ion t ends not t o display well on ASCI I devices, so you probably dont want t o do t his int eract ively from t he m ysql program unless you want your t erm inal window t o t urn int o a horrible m ess of gibberish and possibly even t o lock up . I t s m ore com m on t o use t he inform at ion for display in a web page. Or you m ight send it t o t he client for downloading, t hough t hat is m ore com m on for non- im age binary dat a such as PDF files. Downloading is discussed in Recipe 17.10 . Displaying an im age in a web page is done by including an img t ag in t hat page t hat t ells t he client s web browser where t o get t he im age. I f youve st ored im ages as files in a direct ory t hat t he web server has access t o, you can refer t o an im age direct ly. For exam ple, if t he im age file iceland.j pg is locat ed in t he direct ory m cb im ages under t he servers docum ent root , you can reference it like t his: img src=mcbimagesiceland.jpg I f you use t his approach, m ake sure t hat each im age filenam e has an ext ension such as .gif or .png t hat allows t he web server t o det erm ine what kind of Content-Type: header t o send in t he response. I f t he im ages are st ored in a dat abase t able inst ead, or in a direct ory t hat is not accessible t o t he web server, t he img t ag can refer t o a script t hat knows how t o fet ch im ages and send t hem t o client s. To do t his, t he script should respond by sending a Content-Type: header t hat indicat es t he im age form at , a Content-Length: header t hat indicat es t he num ber of byt es of im age dat a, a blank line, and finally t he im age it self as t he body of t he response. The follow ing script , display_im age.pl, dem onst rat es how t o serve im ages over t he Web. I t requires a name param et er t hat indicat es which im age t o display, and allows an opt ional location param et er t hat specifies whet her t o ret rieve t he im age from t he image t able or from t he filesyst em . The default is t o ret rieve im age dat a from t he image t able. For exam ple, t he following URLs display an im age from t he dat abase and from t he filesyst em , respect ively: ht t p: apache.snake.net cgi-bin display_im age.pl?nam e= iceland.j pg ht t p: apache.snake.net cgi-bin display_im age.pl?nam e= iceland.j pg; locat ion= fs The script looks like t his: usrbinperl -w display_image.pl - display image over the Web use strict; use lib qwusrlocalapachelibperl; use CGI qw:standard escapeHTML; use FileHandle; use Cookbook; Default image storage directory and pathname separator CHANGE THESE AS NECESSARY my image_dir = usrlocalapachehtdocsmcbimages; my path_sep = ; Reset directory and pathname separator for WindowsDOS if O =~ MSWini || O =~ dos { image_dir = D:\\apache\\htdocs\\mcb\\images; path_sep = \\; } my name = param name; my location = param location; make sure image name was specified defined name or error image name is missing; use default of db if the location is not specified or is not db or fs defined location location eq fs or location = db; my dbh = Cookbook::connect ; my type, data; If location is db, get image data and MIME type from image table. If location is fs, get MIME type from image table and read the image data from the filesystem. if location eq db { type, data = dbh-selectrow_array SELECT type, data FROM image WHERE name = ?, undef, name or error Cannot find image with name name; } else { type = dbh-selectrow_array SELECT type FROM image WHERE name = ?, undef, name or error Cannot find image with name name; my fh = new FileHandle; my image_path = image_dir . path_sep . name; open fh, image_path or error Cannot read image_path: ; binmode fh; helpful for binary data my size = stat fh[7]; read fh, data, size == size or error Failed to read entire file image_path: ; fh-close ; } dbh-disconnect ; Send image to client, preceded by Content-Type: and Content-Length: headers. print header -type = type, -Content_Length = length data; print data; exit 0; ---------------------------------------------------------------------- sub error { my msg = shift; print header , start_html Error, p escapeHTML msg, end_html ; exit 0; }

17.9 Serving Banner Ads