Mohamed Mufeed
Mohamed Mufeed

Reputation: 1560

What is the right way to clean stored temporary files in php?

I am trying to figure out a way to clean my temporary storage space using php. I know I can setup cron jobs but, is there a way to do it from php itself?

I use a temporary storage folder for storing generated pdf files for user to download. I have managed to force an expiry on the file so it will no longer be available publically to access after 3 minutes. Now the issue. Although the file is not accessible publically, It is still stored in my server. I have coded something like this to clean up the storage.

/** from the main thread */
if (rand(1, 100) <= 5) {
    Reports::clean();
}

/** the clean function */
public static function clean()
{
    $path = static::getStoragePath();
    if($dir_handle = opendir($path)) {
        while (($fileName = readdir($dir_handle)) !== false) {
            $file = $path . '/' . $fileName;
            
            if (!is_file($file)) 
                continue;

            // If file is older that 3 minutes delete it
            if (time() - filemtime($file) > static::$expires) {
                unlink($file);
            }
        }
        closedir($dir_handle);
    }
}

so this will clean up the storage randomly. Mostly this is fine. but the issue is when the storage clean up starts this slow down that request like turtle.

So I thought of creating a cronjob. But is there a right way to do this from php itself?

Note: I am using slim-4, also don't have much expertise on setting up cronjobs. So any resource will also be helpful

Upvotes: 1

Views: 1585

Answers (3)

TomiL
TomiL

Reputation: 687

This is a bad concept, use cronjob scheduler for this job. Here is bash oneliner to delete all files in folder /tmp/some_path if folder content exceeds 10MB (please modify accordingly to your needs):

SIZE=$(du -bs --block-size=1M /tmp/some_path | cut -f1); if [[ $SIZE -gt 10 ]];then echo "Folder '/tmp/some_path' has size ($SIZE MB)."; rm -r /tmp/some_path/*; fi

You can past this code into script.sh (include shebang eg. for bash #!/bin/bash at the top and make file executable ie. chmod +x script.sh), Then append new line to cronjob scheduler (e.g. crontab -e) to check folder size every hour:

0 * * * * <path_to_the_script>/script.sh

You can find more about cronjobs here: https://crontab.guru

Upvotes: 0

Markus AO
Markus AO

Reputation: 4889

In your implementation, whenever the clean-up routine hits the main thread, depending on the volume of files in your PDF directory, it may create a significant lag in the response.

As noted in the other comments/answers, a cron job would indeed be the "standard" way to handle this. However, if you don't have access to cron jobs, or simply prefer a pure PHP solution, there are a couple of possible approaches, aside what you're already doing.

  1. Keep a log of the created files along with a creation timestamp. When the clean routine is called, instead of doing a full directory scan with modified time checks, delete on the basis of your record, and purge deleted entries from the record. Store your record e.g. as a JSON file, or as CSV/TSV. This should provide a significant speed-up in cases where there's a significant volume of files, given the reduction in filesystem access.

  2. If you don't want to bother your users with the clean-up lag, move the routine from user-facing files to admin-only files, or do an admin user check, and adjust the clean-up frequency trigger (in OP with 1:20) to match admin usage frequency. This may of course reduce the clean-up frequency (if admins aren't around), but will take the load off the public.

  3. Finally, obviously, become Mr. Cron and trigger the cleanup manually once in a while, on a daily basis or before your server runs out of space. In general, unless you are very tight on space, it doesn't seem to be necessary to clean up every 20 page calls or so. I have no idea of the volume of PDFs generated, traffic happening, or server resources, so it's difficult to come up with recommended figures on the clean-up frequency.

Upvotes: 2

Short answer: no.

PHP has no way of self-triggering any actions.

Create a script (or a command if it's a framework) and trigger it with a cronjob.

Upvotes: 3

Related Questions