Serve then remove temporary file using Laravel

Let’s say you are running a report for the user. You generate some temporary file to give to the user and now you have this zombie pdf file sitting out there in your /tmp directory. How do you clean it up? Why not do it directly after you serve to the user? Here are a couple of options. The first option just cleans up the file after the application has served the response.

1
2
3
4
5
6
7
8
9
10
11
Route::get('get-file', function()
{
$filename = storage_path() . '/testing.txt';

App::finish(function($request, $response) use ($filename)
{
unlink($filename);
});

return Response::download($filename);
});

If you don’t like the idea of putting App::finish in your controller action or route closure then you could always use a helper to do your downloads. This will let you call: ResponseHelper::downloadAndDelete($filename);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\HttpFoundation\File\Exception\FileException;

class ResponseHelper extends Illuminate\Support\Facades\Response
{
static public function downloadAndDelete($fileName, $name = null, array $headers = array())
{
$file = new File((string) $fileName);
$base = $name ?: basename($fileName);
$content = file_get_contents($fileName);

$response = Response::make($content);

if (!isset($headers['Content-Type']))
{
$headers['Content-Type'] = $file->getMimeType();
}

if (!isset($headers['Content-Length']))
{
$headers['Content-Length'] = $file->getSize();
}

if (!isset($headers['Content-disposition']))
{
$headers['Content-disposition'] = 'attachment; filename=' . $base;
}

foreach ($headers as $headerName => $headerValue)
{
$response->header($headerName, $headerValue);
}

unlink($fileName);

return $response;
}
}

Finally, another idea is to register your App::finished closures in another class or as event listeners. I’ll leave that up to you to implement.