in reply to Re: gnuplot and CGI
in thread gnuplot and CGI

I've made progress but I'm still having trouble getting the image to display in the browser, I'm hoping I can get input from someone.

The following code prints the A OK message and then prints
Content-type: image/png Content-type: text/html 
Software error:
Failed to open pipe: No such file or directory
#!/usr/bin/perl -w use CGI qw( :standard ); use CGI::Carp 'fatalsToBrowser'; print "Content-type: text/plain\n\n"; print p( "A OK" ); print "Content-type: image/png\n\n"; my $data = "05056670.txt"; my $plot = plotdata(); sub plotdata { open my $graph => "| gnuplot" or die "Failed to open pipe: $!\n"; my $graph; print $graph <<"gnu"; set terminal png color set output set xdata time set timefmt "%Y%m%d" set key left top title "Legend" box set grid xtics ytics set yrange [700:] set format x "%Y" set xlabel "Year" set ylabel "Sodim, water, filtered, milligrams per liter" set title "05056670 Western Stump Lake Major Ions" plot "$data" using 2:3 title "P00930 Sodium dissolved" gnu close $graph or die "Failed to close pipe: $!\n"; }
The following code appears to work at the command prompt because it prints the text and a bunch of strange characters, but it this is what the browser shows:
A OK 

Content-Type: image/png 
no image.
!/usr/bin/perl -w use CGI qw( :standard ); use CGI::Carp 'fatalsToBrowser'; my $q = new CGI; print $q->header("text/html"); print p(" A OK "); my $img = `gnuplot setcmds`; print $q->header("image/png"), $img;
setcmds file:
set terminal png color set output set xdata time set timefmt "%Y%m%d" set key left top title "Legend" box set grid xtics ytics set yrange [700:] set format x "%Y" set xlabel "Year" set ylabel "Sodim, water, filtered, milligrams per liter" set title "05056670 Western Stump Lake Major Ions" plot "05056670.txt" using 2:3 title "P00930 Sodium dissolved"
I'm sure I'm not doing something correctly, but I don't know what.

Replies are listed 'Best First'.
Re^3: gnuplot and CGI
by tmoertel (Chaplain) on Nov 09, 2004 at 23:02 UTC
    You can only send one response at a time, but you are trying to send back two responses smashed together (one blob of text and one image):
    print "Content-type: text/plain\n\n"; print p( "A OK" ); print "Content-type: image/png\n\n";
    Only the first header is interpreted as a valid header, and hence the browser thinks it is seeing one big text response.

    What you must do is send back one response per request. The trick is to set the src attribute of your first response's IMG element in such a way as to cause the client's browser to call your CGI back and ask for the image.

    This is the idea:

    1. The client's web browser requests your page.
    2. Your CGI receives request and sends back a text/html response. The HTML includes an IMG element whose src attribute points back to your CGI and passes in an "I want the image" parameter.
    3. The client's browser receives your response, parses the HTML, and then tries to load the image. In doing so, it calls your CGI again (the src attribute points to it), asking for the image.
    4. Your CGI checks the request parameters and notices the "I want an image" parameter. The CGI then generates the image and sends back an image/png (or whatever type is appropriate) response.
    5. The client receives the image and finishes rendering the page.
    6. It's happy time. Dance.

    For a complete example that uses this technique, see the script referenced at the end of The Mobile Weather Problem and its solution on my site.

    Cheers,
    Tom

      Thank you so much! I now have the graph displaying in the browser in my test case!

      I knew just enough CGI to know that it was possible. I'm off to study your example - I appreciate that you have made it available online.