4

I have a form where I am uploading files to the "sites/default/files" directory. I am using the managed_file type in my form API definition. This is all working fine and I notice that in the file_managed table, I see my uploaded files with a status of 0 meaning they are temporary. I was under the impression that these files that have a status of 0 should get deleted, not only from the database, but physically from the server on cron run, but I do not see this happening. I see lots of files with a status of 0 and they are NOT in the file_usage table, so they are not being used by anything, yet if I force a cron run, I don't get errors, yet the files do not get deleted either. Am I misunderstanding how this system works?

Thanks

2
  • 1
    Are the files older than 6 hours? Temporary files don't get deleted until the DRUPAL_MAXIMUM_TEMP_FILE_AGE constant is met which is 21600 seconds. Don't completely quote me on that but last time I checked I believe it was true :) May 30, 2015 at 2:04
  • And they also may be in queue to be deleted, some items only get queued on cron, like field deletion for instance. Those are put in a queue and deleted over time, not sure if file is one of those items. May 30, 2015 at 2:05

2 Answers 2

4

They are deleted, but during cron tasks, and just when:

The code that deletes those temporary files is contained in system_cron().

  // Remove temporary files that are older than DRUPAL_MAXIMUM_TEMP_FILE_AGE.
  // Use separate placeholders for the status to avoid a bug in some versions
  // of PHP. See http://drupal.org/node/352956.
  $result = db_query('SELECT fid FROM {file_managed} WHERE status <> :permanent AND timestamp < :timestamp', array(
    ':permanent' => FILE_STATUS_PERMANENT,
    ':timestamp' => REQUEST_TIME - DRUPAL_MAXIMUM_TEMP_FILE_AGE
  ));
  foreach ($result as $row) {
    if ($file = file_load($row->fid)) {
      $references = file_usage_list($file);
      if (empty($references)) {
        if (!file_delete($file)) {
          watchdog('file system', 'Could not delete temporary file "%path" during garbage collection', array('%path' => $file->uri), WATCHDOG_ERROR);
        }
      }
      else {
        watchdog('file system', 'Did not delete temporary file "%path" during garbage collection, because it is in use by the following modules: %modules.', array('%path' => $file->uri, '%modules' => implode(', ', array_keys($references))), WATCHDOG_INFO);
      }
    }
  }

If the files are not getting deleted, and you don't see any error message in the watchdog log database, then you need to verify cron tasks are executed and the files are older than 6 hours. In the other cases, you should get an entry in the watchdog database table, even if that would be as generic as Could not delete temporary file.

3
  • Well I guess I just wasn't being patient enough. The weird thing is that I waited overnight and checked the files and they were not deleted, but when I came back into the office on Monday from the weekend, all the files WERE deleted. I checked my DRUPAL_MAXIMUM_TEMP_FILE_AGE constant and it was set at 21600, but the files did not delete overnight. Anyway, they are deleted now so at least I know it is working now. THANKS
    – Erich H.
    Jun 1, 2015 at 15:52
  • @apaderno how to test if that cron task is executed ? i have temporary files that are deleted from the database after 6hours but not delete on server and nothing log
    – Matoeil
    Oct 21, 2021 at 9:42
  • 1
    @Matoeil Drupal always records the last time cron tasks are executed, in the system.cron_last state (Drupal 8) or in the cron_last persistent variable (Drupal 7). Checking why files aren't physically deleted is a different matter; that requires debugging.
    – apaderno
    Oct 21, 2021 at 10:45
0

Unused files are not converted anymore to temporary per default https://www.drupal.org/node/2891902 For them to be deleted after the cron, that conf must be added: $config['file.settings']['make_unused_managed_files_temporary'] = TRUE;

Some module seems to interfere with that behaviour (see apaderno reply). In that case i used:

function amu_unused_file_delete_cron() {
  // get all files ids
  $fids = Drupal::entityQuery('file')->execute();
  $file_usage = Drupal::service('file.usage');
  // loop all fids and load files by fid
  foreach ($fids as $fid) {
    $file = Drupal\file\Entity\File::load($fid);
    $usage = $file_usage->listUsage($file);
    // check if file not used
    if (count($usage) == 0) {
      $file->delete();
    }
  }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.