Beefy Boxes and Bandwidth Generously Provided by pair Networks
The stupid question is the question not asked
 
PerlMonks  

cgi download and delete file

by teddyttas (Novice)
on Aug 15, 2013 at 09:19 UTC ( #1049533=perlquestion: print w/ replies, xml ) Need Help??
teddyttas has asked for the wisdom of the Perl Monks concerning the following question:

Hi Monks!

I would like to have your advice on the following problem:

I am making a small webapp and my purpose is to create a number of text files, compress them, download as zip file and erase.

For the moment I've been able to create the directory with the file, put them in a zip file and to download, but I can't erase the zip file. Well..It's not totally true. The problem is that if I do it, it compromises the download. My question would then be : Ho can I postpone the file elimination or, how can I check that the file has been totally completed before I erase it?

I know about the existence of File::Temp, but as I need this zip file just once, I think it would be simpler to just delete it. Here is a part of the code

sub write_and_download{ [...] $self->generate_zip(); $self->download_file(); my $filename = "temporary/" . $projectname . ".zip"; unlink $filename; }; sub download_file{ my $self = shift; my $downloadfile = $projectname . ".zip"; my $fullpathdownloadfile = "temporary/$downloadfile"; my $output = ''; my $buffer = ''; open my $fh, '<', $fullpathdownloadfile or return error_handler("Error: Failed to download file <b>$down +loadfile</b>:<br>$!<br>"); while (my $bytesread = read($fh, $buffer, 1024)) { $output .= $buffer; } close $fh or return error_handler("Error: Failed to download file <b>$down +loadfile<b>:<br>$!<br>"); my $downloadfilesize = (stat($fullpathdownloadfile))[7] or return error_handler("Error: Failed to get file size for <b>$ +downloadfile<b>:<br>$!<br>"); $self->header_props( '-type' => 'application/x-downl +oad', '-content-disposition' => "attachment;filename +=$downloadfile", '-content_length' => $downloadfilesize, ); return $output; };

I thank you from now for your help

Comment on cgi download and delete file
Download Code
Re: cgi download and delete file
by flexvault (Parson) on Aug 15, 2013 at 10:11 UTC

    teddyttas,

    I have to guess that another script is going to use the zip file you create, since you don't call a subroutine or use the zip file in any way. A couple things can be done:

    • Let the other script delete the zip file.
    • Delete old zip files when creating new zip files. (see 'stat')
    • Call the other script before doing the 'unlink'.
    • Use 'sleep' to wait to do the 'unlink'.
    • etc. etc. etc.
    I think this comes down to "you know what you want to do", but we don't. Maybe a description of the timing consideration would help give you a better answer.

    Regards...Ed

    "Well done is better than well said." - Benjamin Franklin

Re: cgi download and delete file
by poj (Priest) on Aug 15, 2013 at 10:26 UTC
    You could create the zip 'on-the-fly' so no file to delete
    #!perl use strict; use Archive::Zip; use CGI qw(:standard); my $zip = Archive::Zip->new(); $zip->addFile('c:/temp/inet/test.pdf','test.pdf'); print header(-type=>'application/zip',-attachment=>'download.zip'); binmode(STDOUT); $zip->writeToFileHandle(*STDOUT);
    poj
Re: cgi download and delete file
by Anonymous Monk on Aug 15, 2013 at 11:49 UTC
    If you're using a variant of Unix for the web server, you can delete the file as soon as the download is initiated. The OS won't fully delete the file as long as a process has it open. (Of course, resuming the download will not work.)
Re: cgi download and delete file
by sundialsvc4 (Abbot) on Aug 15, 2013 at 12:37 UTC

    You know that Private SNAFU is always on duty:   the mere fact that you zipped-up a bunch of files and pushed them to an HTML stream doesn’t mean that they arrived, any more than it does at the Post Office.   I would therefore design this program to build the Zip files, then remove the files from whence they were made (if appropriate), then put that file into a “to be downloaded” directory under some appropriate name.   From these, when the user requests a download, the file is renamed in some slight way to indicate that it “has been or is-being downloaded.”   (Renaming ahead-of-time avoids any file contention issues.   Moving it to a different directory ahead-of-time does the same thing.)   But in every step you have thus given yourself a way out.   If the download did not for whatever reason succeed, the data is still there and the process could be repeated.

      Thank you very much! Anyway, I think there is something I am getting wrong... When I use the cgi::application's header_prop (in the download_file subroutine) what I'm actually doing is a redirection to the download window, is it right? Cause I tried to make a redirection after the execution of the subroutine, but in this case the download doesn't start. If I put a sleep command after the subroutine, the script executes before the sleep command and then launches the download. So...I don't really understand this behaviour. I tried :
      $self->download_zip(); sleep 5; my $filename = "temporaneo/" . $self->session->param("nom_projet") + . ".zip"; unlink $filename;
      and
      $self->generate_zip(); $self->download_zip(); return $self->redirect("http://delete.cgi");
      What I was trying to do was following your advice: put the zip file in another directory and, if succeed, redirect to another run mode that erases the file, otherwise stay on the page and relaunch the download.
        Okay, I think I got the solution to my last question... it was simple. In fact I solved it in the following way...
        $self->generate_zip(); my $output = $self->download_zip(); #here I can do what I want. unlink and so on.. my $filename = "temporaneo/" . $self->session->param("nom_projet") + . ".zip"; unlink $filename; #and only then I stream the output return $output;
        I can now redirect to another runmode passing the $output variable and solve the problem as you suggested. thank you very much!

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (13)
As of 2014-09-22 17:30 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (198 votes), past polls