Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Donate Today!

Do you enjoy these
technical forums?
Donate Today! Click Here

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

execute code upon download completionHelpful Member! 

danno74 (IS/IT--Management)
11 Aug 11 9:11
Greetings,

Currently, I have a page that once a user selects a file they want to download, it moves and renames the file from another folder to the download folder, then executes the file download.

What I want to accomplish is to delete the file after the download of it has completed. I tried to execute a simple sleep command within the page, but seems to execute the sleep command prior to the header command to download the page:

CODE


<?php

        $rdmint=rand(10000, 99999);
        $hiddenpath='/hiddenpath/';
        $downloadpath='/download/';
        $filename='bigfile';
        $destnewfile="$filename$rdmint.zip";
        $file="$hiddenpath$filename.zip";
        $newfile="$downloadpath$destnewfile";


        if(copy($file, $newfile))
        {
        echo "File copied successfully.";
        }
        else
        {
        echo "Failed to copy $file, please contact the Helpdesk.";
        }

        header("Location: https://download/$destnewfile");
        

        sleep(60);


        if (unlink($newfile))
        {
        echo "File moved from server successfully.";
        }

?>

Any ideas on how I can accomplish this? Will putting the sleep and unlink cmds in another file alleviate the problem possibly?

Thank you for your time.

- Dan
sleipnir214 (Programmer)
11 Aug 11 10:24
Unfortunately, once the user's browser has received the "Location" header, it immediately severs the current connection and establishes a new one with the specified URL.  So anything after the header('Location: ...') invocation will not run.

Instead, you can make PHP stream the file to the browser.  In the online manual entry for header() (http://www.php.net/manual/en/function.header.php), Example #1 shows how to do this by sending the browser Content-type and Content-Disposition headers.  The example code reads:

CODE

<?php
// We'll be outputting a PDF
header('Content-type: application/pdf');

// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');

// The PDF source is in original.pdf
readfile('original.pdf');
?>


Want to ask the best questions?  Read Eric S. Raymond's essay "How To Ask Questions The Smart Way".  TANSTAAFL!

danno74 (IS/IT--Management)
11 Aug 11 11:14
Thanks sleipnir.

Actually, that is what my page currently does, but the files are too large to pass through readfile, after I get past 80MB, I get errors or empty files downloaded. I now have 300-400MB+ files that I cannot split up. Thus my attempts at this current workaround.

 
sleipnir214 (Programmer)
11 Aug 11 11:23
Then you might try a housekeeping function.

Create a PHP include file, which you include in other scripts where appropriate.  Have that included script-code scan your download directory and delete any file that is older than a certain amount of time.

Of course, the fun part about this way is the definitions of "where appropriate" and "a certain amount of time".  If you run this script too often in your site, you can have processing overhead you don't want, so be circumspect where in your site you run it.  And you want, I'm sure, to give your users a reasonable amount of time to finish their downloads before deleting the file, but not to leave it there long enough to be found.

If you have sufficient control over the server where this runs, you could even set up a cron job (or whatever is equivalent on non-Unix-like OSes) to do this deletion on its own.


Want to ask the best questions?  Read Eric S. Raymond's essay "How To Ask Questions The Smart Way".  TANSTAAFL!

Helpful Member!  jpadie (TechnicalUser)
11 Aug 11 11:29
something is probably wrong at your end or perhaps in your browser that you are using for testing.

however, there is a workaround for your original query

1. when the user clicks the download link on the first page, instead of loading a new page in the main window, open up an iframe with javascript and download the file through that.
2. using (for example) jquery on the main page, and assuming that the iframe is called myIFrame, use this function to test when the content is downloaded

CODE

jQuery('#myIFrame').load(function(){
 //
});
3. in the anonymous function pass a variable back to the server via ajax that will cause the server to delete the file.

alternatively, set a time out on the file after which it will be deleted (do this via a db entry or a flat file or something that you check with a cron job, or just check the file creation time in the file system).
 
danno74 (IS/IT--Management)
12 Aug 11 15:02
Thanks for your suggestions. I'm interested in hearing what solutions you may have for the problems I was having with the original code. I have posted this questions on many forums with this original code and never found a solution - maybe I was asking it in a way people couldn't understand...


Here code I'm currently using:

CODE


 //Location of file, must be out of web root
      $file_location='/download/software.exe';
      
      //supply the right file format      
      header('Content-type: application/exe');
      header('Expires: 0');
      header('Pragma: public');
      
      //force browser to prompt to download file
      
      header('Content-Disposition: attachment; filename="software.exe"');
    
      
      //finally echo content
      readfile($file_location);

I get a server error, problem has nothing to do with browser -

[Fri Aug 12 14:58:53 2011] [error] [client ] PHP Fatal error:  Allowed memory size of 134217728 bytes exhausted (tried to allocate 358830081 bytes) in /file.php on line 24, referer: https://success.php

Help is immensely appreciated.... I'm only asking because I know very little about javascript and jquery.

- Dan
      
 
jpadie (TechnicalUser)
12 Aug 11 15:38
try this

CODE

//Location of file, must be out of web root
$file_location='/download/software.exe';

if(!file_exists($file_location) || is_readable($file_location)):
    echo 'problem';
    exit;
endif;
//supply the right file format      
header('Content-type: application/octet-stream');
header('Expires: 0');
header('Pragma: public');

//force browser to prompt to download file
header('Content-Disposition: attachment; filename="software.exe"');
$size  = filesize($file_location);
header('Content-Length: ' .$size ); //explicitly provide the file size

//*** EITHER *** ///
ini_set('memory_limit', ($size * 1.5));
readfile($file_location);
exit; //always explicitly exit

//** OR **//
$fh = fopen ($file_location, "rb");
while (!feof($fh)):
    echo fread($fh, 100000);
endwhile;
fclose($fh);
danno74 (IS/IT--Management)
12 Aug 11 15:56
You know jpadie, I was about to reply with the error I normally get when I do this, and it run without a hitch. I also had to set

CODE

ini_set("max_execution_time", "900");

It works now! We're going to do some testing - do you know if we get say 5 users doing this at once, will the memory limit be exceeded, or is it on a per execution basis?
jpadie (TechnicalUser)
12 Aug 11 16:10
memory_limit sets the maximum amount of time that the relevant script is allowed to use.  so per connection (essentially).

add this to the start or expressly make sure that output buffering is turned off.

CODE

@ob_end_clean();

i had thought that readfile() did not buffer the content but your experience suggests either that it does buffer or that output buffering was turned on and set to quite a high value.   I had meant to add the line into the code I posted above.

i am surprised that max_execution_time was also needed as normally things that happen externally to the script (i.e. database operations, file reads/writes, buffer outputs) are not counted in the time that the script itself takes to run.   

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close