Deleting a file after user download it

Php

Php Problem Overview


I am using this for sending file to user

header('Content-type:  application/zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($file);

I want to delete this file after user downloads it, how can i do this?

EDIT: My scenario is like that, when user hits download button, my script will create a temporary zip file and user download it then that temp zip file will be deleted.

EDIT2: OK best way seems running a cron job that will be cleaning temp files once an hour.

EDIT3: I tested my script with unlink, it works unless user cancel the download. If user cancel the download, zip file stays on the server. So that is enough for now. :)

EDIT4: WOW! connection_aborted() made the trick !

ignore_user_abort(true);
if (connection_aborted()) {
    unlink($f);
}

This one will delete the file even if user cancel the download.

Php Solutions


Solution 1 - Php

unlink($filename);

This will delete the file.

It needs to be combined with ignore_user_abort()Docs so that the unlink is still executed even the user canceled the download.

ignore_user_abort(true);

...

unlink($f);

Solution 2 - Php

I always use the following solution, using register_shutdown_function:

register_shutdown_function('unlink', $file);

Solution 3 - Php

There is no any correct way to detect whether file was completely downloaded by user or not.
So the best way will be to delete file after some period of inactivity.

Solution 4 - Php

connection_aborted() never worked for me. Although ob_clean() works exactly as it should. Hope this help others aswell

header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="' . $file . '"');
header('Content-Transfer-Encoding: binary');
header('Accept-Ranges: bytes');
ob_clean();
flush();
if (readfile($file))
{
  unlink($file);
}

Solution 5 - Php

I couldn't find something which worked for me, so I came up with this, which seems to work well for me:

header('Content-type: application/zip'); //this could be a different header 
header('Content-Disposition: attachment; filename="'.$zipName.'"');
	
ignore_user_abort(true);
	
$context = stream_context_create();
$file = fopen($zipName, 'rb', FALSE, $context);
while(!feof($file))
{
	echo stream_get_contents($file, 2014);
}
fclose($file);
flush();
if (file_exists($zipName)) {
	unlink( $zipName );
}

I hope that helps someone

Solution 6 - Php

I too have very similar functionality in one of my website. It will be like deleting randomly created folder & zip file after/cancelling download. I try to explain it here, may be someone find it useful.

skin.php:
This page contains download link such as "http://mysite.com/downoload/bluetheme"

.htaccess:
I have following rule in htaccess file to redirect the download request to a php file. [download.php].

RewriteRule ^download/([A-Za-z0-9]+)$ download.php?file=$1 [L]

download.php:

include "class.snippets.php";
$sn=new snippets();
$theme=$_GET['file'];
$file=$sn->create_zip($theme);
$path="skins/tmp/$file/$file.zip";
$config_file="skins/tmp/$file/xconfig.php";
$dir="skins/tmp/$file";

$file.=".zip";
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=$file");
header("Pragma: no-cache");
header("Expires: 0");
readfile($path);

//remove file after download  
unlink($path);
unlink($config_file);
rmdir($dir);

so on request download.php will create directory with a random name using snippets class. Inside the directory it will create a zip file. after the download/cancelling the request all the files and the directory will be deleted.

Solution 7 - Php

For those who face the "extra bytes at the begining of file" issue, I would recommend to add buffer cleaning functions before readfile, as suggested in this post:

https://stackoverflow.com/a/51083411/16381972

@ob_start('');  //@ supresses a warning  
//header entries
ob_end_clean();
ob_clean();
readfile($file);

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionUtku DalmazView Question on Stackoverflow
Solution 1 - PhpbrettkellyView Answer on Stackoverflow
Solution 2 - PhpLars van den BoschView Answer on Stackoverflow
Solution 3 - PhpzerkmsView Answer on Stackoverflow
Solution 4 - PhpSina ariaView Answer on Stackoverflow
Solution 5 - PhpBren1818View Answer on Stackoverflow
Solution 6 - PhpvkGunasekaranView Answer on Stackoverflow
Solution 7 - PhpsporteiroView Answer on Stackoverflow