LLLLLLL Posted August 31, 2010 Share Posted August 31, 2010 On PHP 5.2.14. I want to make files downloadable from my website. This seems easy enough: <?php $file = "downloads/someFile.txt"; // Set headers header( "Content-Description: File Transfer" ); header( "Content-Type: application/force-download"); header( "Content-Length: " . filesize( $filename ) ); header( "Content-Disposition: attachment; filename=$file"); // header( "Content-Transfer-Encoding: binary"); readfile( $file ); unlink( $file ); ?> You'll notice, however, that I have "unlink" at the end of this file. That's exactly what I want: to remove the file from the server once it has been downloaded, to prevent anyone else from downloading it. Here's the conundrum: When the user navigates to this URL, browsers offer the choice of Open/Save/Cancel. I don't want users to "open", and if the user presses "cancel", well then I probably don't really want the file deleted. In short: I want the file SAVED, only. And I want to delete the file immediately after it has been downloaded. Thoughts? Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/ Share on other sites More sharing options...
premiso Posted August 31, 2010 Share Posted August 31, 2010 You cannot control how the browsers asks the users what they want to do. You cannot tell if the user "truly" downloaded the file either. So yea, you are stuck between a hardspot and a rock. Sorry mate. EDIT: However, using a Java or Flash application, this may be possible, but I am not 100% on that (or at least a bandwidth monitor for the current connections should be possible). I would suggest looking into that route. Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/#findComment-1105766 Share on other sites More sharing options...
LLLLLLL Posted August 31, 2010 Author Share Posted August 31, 2010 I kinda figured. Argh. Related question: I've read that readfile() may not be the best option, especially for large files. Some of the files I'm providing are around 10MB. How would you change the code to handle that? Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/#findComment-1105769 Share on other sites More sharing options...
jayarsee Posted August 31, 2010 Share Posted August 31, 2010 I know how you can do it. You could write some simple CLI PHP that hooks into the Apache logs (assuming you're using that) to see what the per-file / per-IP activity was and make a decision about what to do with the file that way. Just setup your logs with %B: http://httpd.apache.org/docs/2.0/mod/mod_log_config.html#formats You can compare how many bytes were transferred with the actual bytes to see if the file was downloaded or not. Just use exec() (or its cousins) with cat and grep to find the lines of the log you need. I bet you could do it in less than 50-100 lines. Let me know if I can clarify further. Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/#findComment-1105772 Share on other sites More sharing options...
jayarsee Posted August 31, 2010 Share Posted August 31, 2010 This comment from the PHP Manual seems to address your second question: To anyone that's had problems with Readfile() reading large files into memory the problem is not Readfile() itself, it's because you have output buffering on. Just turn off output buffering immediately before the call to Readfile(). Use something like ob_end_flush(). Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/#findComment-1105779 Share on other sites More sharing options...
premiso Posted August 31, 2010 Share Posted August 31, 2010 Addressing the readfile question, aside from jayarsee's information on the output buffering, another option is a custom user function: here http://us.php.net/manual/en/function.readfile.php#88549 Which is: function readfile_chunked ($filename,$type='array') { $chunk_array=array(); $chunksize = 1*(1024*1024); // how many bytes per chunk $buffer = ''; $handle = fopen($filename, 'rb'); if ($handle === false) { return false; } while (!feof($handle)) { switch($type) { case'array': // Returns Lines Array like file() $lines[] = fgets($handle, $chunksize); break; case'string': // Returns Lines String like file_get_contents() $lines = fread($handle, $chunksize); break; } } fclose($handle); return $lines; } I have used this and it has worked for me. It may be able to be optimized a bit, but yea. Quote Link to comment https://forums.phpfreaks.com/topic/212206-download-file-question/#findComment-1105846 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.