Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

CGI and image

by urizackhem (Initiate)
on Dec 13, 2016 at 17:22 UTC ( [id://1177719]=perlquestion: print w/replies, xml ) Need Help??

urizackhem has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I have a small perl script to serve some data. I wanted to add an image. The problem is that it prints characters and not the image. What's wrong?
my $q = CGI->new(); say $q->header() , $q->start_html("Z weather"); say "<center>"; say "<p><strong>Weather measurements</p></strong>"; my $image; my $imageHandle; local $/ = undef; open ($imageHandle , "< $imagefile"); binmode $imageHandle; $image = <$imageHandle>; close ($imageHandle); my $r = CGI->new(); print $r->header(-type=>'image/png') , $image; say "</center>"; say $q->end_html();
Thank you very much, U

Replies are listed 'Best First'.
Re: CGI and image
by Corion (Patriarch) on Dec 13, 2016 at 17:31 UTC

    That's not how HTTP works.

    Your HTML and the image it references are two separate HTTP requests. Your script tries to answer both requests in one response. This approach will not work.

    You need to wait for the image request and then send the image data. If you want/need to carry information from the page request to the image request, either use a cookie or pass the information in the image URL as a CGI parameter.

      Technically, it could be one HTTP request. He could convert the image data to base64 and use a data uri. There's a URI::Data module that might be helpful in that regard.
        Technically, it could be one HTTP request. He could convert the image data to base64 and use a data uri.

        That won't work with all browsers. See http://caniuse.com/datauri. (Don't think that people have stopped using ancient IEs. And don't think that the browsers listed there are ALL browsers that exist.) Plus, it wastes a lot of bandwitdh, especially if the image is static. Using a classic HTTP(S) URL for the image allows the browser and all proxies between browser and server to cache the image, so it is transmitted only once, whereas the data URL "solution" sends the image for every request, with an additional overhead of 33% due to base64 encoding.

        Alexander

        --
        Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
Re: CGI and image
by NetWallah (Canon) on Dec 13, 2016 at 21:03 UTC
Re: CGI and image
by bart (Canon) on Dec 18, 2016 at 11:19 UTC
    Traditionally, I would have answered in the same way as NetWallah did in his reply. That is: send the HTML file with a link to the image, for which you don't even need to use CGI. That's how we've done it for almost 20 years already.

    But in the modern world, there is another option, and that is much closer to your own solution, and that is to embed the PNG file into your HTML. For that, you have to base-64 encode your image file data, slap a content-type in a form of header on it and put that as the source of the <img> tag, using the data: protocol. The code could look like this:

    use MIME::Base64; printf '<img src="data:image/png;base64,%s">', encode_base64($image);
    where the rest of you code can remain the same.

    I would not recommend this for huge files, as it increases the transfer byte size by 33%, but for tiny images of a few k at most that is definitely a good alternative, since it limits the number of server requests.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1177719]
Approved by herveus
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others wandering the Monastery: (7)
As of 2024-04-18 09:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found