Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

deleting a file after loading

by belize (Deacon)
on Nov 28, 2000 at 20:08 UTC ( #43686=perlquestion: print w/replies, xml ) Need Help??

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

I have a program that generates an image, saves it to a file, then loads it on a page using the <IMG..> tag. i have tried to generate the image on the fly and load it directly to the page, but I only get ASCII text instead of the binary image.

My question is that i would like to delete the image AFTER it loads. I have tried the UNLINK function, but the image ends up being deleted prior to loading.

Is there a way to delete the file AFTER it has loaded?

Replies are listed 'Best First'.
Re: deleting a file after loading
by fundflow (Chaplain) on Nov 28, 2000 at 20:21 UTC
    A common practice is to create a file and then unlink() it immediately. The file will not show up further but will be physically erased only when it is closed.

Re: deleting a file after loading
by chipmunk (Parson) on Nov 28, 2000 at 20:24 UTC
    One possibility is to delete old files at the beginning of the script. When your script is executed by the web server, it could first delete all its images files that are older than 5 minutes, and then create a new image file. The five minute period is important in case your script is run by more than one user at the same time. Here's a quick example:
    my $time = time; my $image_dir = '/path/to/script\'s/private/image/dir'; opendir(DIR, $image_dir) or die "Can't opendir $image_dir: $!\n"; while (defined(my $filename = readdir(DIR))) { next unless -f "$image_dir/$filename"; next unless time - (stat(_))[9] > 300; unlink("$image_dir/$filename") or warn "Can't unlink $image_dir/$filename: $!\n"; }
Re: deleting a file after loading
by jepri (Parson) on Nov 28, 2000 at 21:15 UTC
    You still didn't post the source, or explain what you mean by "load it to directly to the page". It sounds like you are dumping the image directly into the html. The correct way to handle this is to output a HTML with has an IMG SRC="http://server.com/cgi-bin/picture-server.pl?picture=1" in it. picture-server.pl then loads the correct image and spits it out.

    This is (presumeably) how the rotating perlmonks banner works - check the page, the html is layer src="http://206.170.14.74/~adfu/servfu.pl?l,perlmonks,5244" width=470 height=75

    So your IMG SRC tag might look like: IMG SRC="http://server.com/cgi-bin/do-image.pl?image-params=blah"
    then do-image.pl would be something like:

    my $params=$query->params('image-params');
    #Calculate image using params
    print $query->header('image/gif');
    #Now dump the image

    The HTML will have to be constructed by another page that sets up the params correctly.

    You may also screw with Apache to do what you want, but I'd rather club myself with the keyboard:

    You can use the following apache config directives to acheive what you want
    Action (provided by mod_action)
    AddHandler/SetHandler (provided by mod_mime)
    There appears to be a "PerlHandler" directive which allows you to stack handlers on a file. However it might be difficult to use, given the number of posts to bulletin boards about it.

    I nearly forgot the most obvious: whack a big button on your output page that says "Click here when finished" and have it point to a script which deletes your file.

    Update: OK, I just read your post above. Read the manual, in this case, Ovid's excellent CGI tutorial

    ____________________
    Jeremy
    I didn't believe in evil until I dated it.

Re: deleting a file after loading
by quidity (Pilgrim) on Nov 28, 2000 at 20:37 UTC

    If you are using GD to make an image, then all you need to do is print the binary data directly to STDOUT when you make it:

    #!/usr/bin/perl use GD; # lifted from GD.pm synopsis... $im = new GD::Image(100,100); $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); $im->transparent($white); $im->interlaced('true'); $im->rectangle(0,0,99,99,$black); $im->arc(50,50,95,75,0,360,$blue); $im->fill(50,50,$red); # Important bit: print "Content-type: image/png\n\n"; binmode STDOUT; print $im->png; exit(0);

    In the page which must access the image, put a normal img tag, but which src="path to script".

Re: deleting a file after loading
by davorg (Chancellor) on Nov 28, 2000 at 20:14 UTC

    Sounds like passing the image directly to the page is the best way to go here. When you got ASCII, were you sending the right Content-Type header?

    --
    <http://www.dave.org.uk>

    "Perl makes the fun jobs fun
    and the boring jobs bearable" - me

      I was using the Content-type: image/gif header. But the image is being displayed within an HTML page which uses the Content-type: text/HTML header.

      When I create the image by accessing a CGI (i.e. <IMG SRC="test.cgi?blah&Blah">, the image comes out fine. But when I access the image using a sub routine (i.e. <IMG SRC="&test"> I get ASCII text.

      I prefer to access via a sub routine because I am accessing a database with variables and the image is drawn using the variables. I am having trouble passing all the variables to an external CGI, but it is easy using a sub routine.

      I'm sure my Perl ignorance is making this much more difficult than it should be.

      You can see what i'm doing at http://www.belizeexplorer.com and using the search function at top. None of hte other links currently work.

Re: deleting a file after loading
by arturo (Vicar) on Nov 28, 2000 at 20:32 UTC

    I guess this depends on your setup, but what you might do is keep the images for, say 15 minutes and then delete them. You could do this with a routine in your image-generating CGI script (as I understand your setup), or (better for so many reasons) you could write a cron job that deletes files that are 15 minutes (or whatever value makes sense) old or older. Perl's -M filetest returns the amount of time, in days, since the file was modified. Assuming nothing's gonna change your files other than creation, the value of -M file will tell you how long since file was created.

    Here's a suitable cron script ... UNTESTED, so check it over =)

    #!/usr/bin/perl -w # delold.pl -- deletes files older than a certain # of minutes use strict; # this is a bit clunky; ideally you'd use the Getopt::Std module, but +hey. my $maxage = shift || 15; #you can call the script with "delold.pl 20 +" and it will delete files that #haven't been modified for 20 minutes. my $dir = shift || "/usr/www/images/temp"; # or wherever makes sense opendir DIR, $dir or die "Can't open $dir: $!\n"; while (my $file = readdir DIR) { next unless -f "$dir/$file"; # skip directories, etc. unlink "$dir/$file" if -M "$dir/$file" > ($maxage / 1440); } closedir DIR;

    Philosophy can be made out of anything. Or less -- Jerry A. Fodor

Re: deleting a file after loading
by cephas (Pilgrim) on Nov 28, 2000 at 21:01 UTC
    Are you trying to spit out the image data straight onto the html page along with the html content? If so that would explain the problem of having the ASCII data showing up. What should work is if you generate your dynamic html, and then have an image tag that looks like:

    <image src="/cgi-bin/imagegenerator.cgi">


    What should be happening is, the browser will make a request to your html generating cgi, then it will start making separate requests for each image it needs, and call your image generating cgi.....

    cephas
      This is the exact problem I am having. But then, the image being generated is based on a search of a database, so that if I reference an external CGI, I have to pass the results of the search, and this I am having trouble doing.

      So, I decided to use a subroutine to generate a file, display the file, then delete the file.

      Part of my program does call the remote CGI when a single record is returned and it is easy to pass the variables for a single image to be drawn.

      If you go to http://www.belizeexplorer.com right now, click on search, and choose Mayan Sites in the Category box, you will see the ASCII come back. Then if you click on the individual links, you will see the program work when it draws a single record.

      I think I will have to go back to creating an image, then deleting them after a period of time.

      Thanks for your post.

      Tony

        What if your search assigned an ID number to each visitor, and you used that ID number with a CGI image generation script to either pull their search terms, or simply retrieve a pre-built image associated with that ID?
        # in the parent CGI script my $id = get_user_id; # just give them a new ID build_image($id, @arguments); # or store the arguments # in a database or something print "<img src='/cgi-bin/fetch_image?$id'>\n"; # or you can be cool and use CGI PATH_INFO stuff: print "<img src='/cgi-bin/fetch_image.cgi/$id.gif'>";
        Then either build the image from the stored information, or retrieve a temp file that matches the ID and send the resulting image, removing the file when it's done.
Re: deleting a file after loading
by AgentM (Curate) on Nov 29, 2000 at 07:30 UTC
    Sounds like a job for IPC. Allowing any number of users to create an arbitrary number of files is a security hole. You'll need to come up with a better mechanism since anyone passing through could flood the server with requests and possibly pose a DoS attack on your filesystem. At least put a limit on how many file can be in existence at any point and time and block until this requirement is met (bad news for people waiting on one guy with a 28K modem...) The best solution would be to create some shared memory or use some other form of IPC where you can then alert the next cgi ("imagegenerator.cgi") what is going on. Minimally, you should be able to store the images (if not the relevant data) in the shared memory (or FIFO, if you prefer, though slower) and present a high-speed cache for your users to enjoy. You control over image production and deletion will be optimized and far easier to deal with. I really hope you're using CGI::Cache, a db level cache, or web server cacheing mechanism. The increase in performance may surprise you. Have fun!
    AgentM Systems nor Nasca Enterprises nor Bone::Easy nor Macperl is responsible for the comments made by AgentM. Remember, you can build any logical system with NOR.

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others rifling through the Monastery: (4)
As of 2021-12-06 21:35 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    R or B?



    Results (33 votes). Check out past polls.

    Notices?