Permanently delete unused / orphaned files in Drupal 8
Asked Answered
C

4

7

We had some serious mistakes in a PDF uploaded to one of our websites. But after "deleting" it from Drupal, it is still accessible through direct links. Drupal doesn't seem to delete it on its own.

I still can find it in the table file_managed, but not in file_usage. Is it safe to delete the database row and file manually?

Already checked all the old questions here on SO but none of them works.

Thank you!

Colpitis answered 3/5, 2018 at 7:45 Comment(3)
Did you try with flushing cache or run cron? I hope this will delete rows automatically because some module remove its deleted data after run cron or cache clear.Horatius
Yeah I tried that too, but it looks like only temporary files will be deleted then. Files in table 'file_managed' with status 1 won't be deleted, even if they are unused. However, setting the status to 0 (temporary) will enable them for garbage collection. Unfortunately this is pretty impractical.Colpitis
Duplicate of: drupal.stackexchange.com/questions/60392/…Grogram
E
3

I know this is an old post, but I had the same problem and found no good answer.

So, after a little bit of trial an error, I came up with this:

<?php

// Some nice ideas from:
// https://mcmap.net/q/1481031/-how-to-set-file-usage-on-drupal-8

$file_storage = \Drupal::entityTypeManager()->getStorage('file');
$fids = Drupal::entityQuery('file')->condition('status', 1)->execute();
$file_usage = Drupal::service('file.usage');

foreach ($fids as $fid) {

  $file = Drupal\file\Entity\File::load($fid);
  $usage = $file_usage->listUsage($file);

  if (count ($usage) == 0) {

    $file->delete();

  }
}

Be careful as the code relies on Drupal reporting the correct number of nodes where the file is used, and that might not always be the case.

Enscroll answered 1/4, 2019 at 19:45 Comment(2)
This code is uses a very dangerous shortcut: count($usage) does not return an array of file usages, according to API docs it returns an array of modules using that file. If the file is used multiple times by the same module, the security check if (count($usage) == 0) fails.Dastardly
api.drupal.org/api/drupal/…Dastardly
O
3

You might wanna create a module that hook on media delete and suppress the associated file

use Drupal\Core\Entity\EntityInterface;
use Drupal\file\Entity\File;

function my_custom_module_entity_delete(EntityInterface $entity) {
  if ($entity->getEntityTypeId() === 'media') {
    $fid = $entity->getSource()->getSourceFieldValue($entity);
    $file = File::load($fid);        
    if ($file) {
      $file_usage = Drupal::service('file.usage');
      $usage = $file_usage->listUsage($file);
      if(count($usage) == 0) {
        $file->delete();
      }
    }
  }
 }
Oldster answered 25/11, 2021 at 14:59 Comment(0)
U
2

You might want to try Fancy File Delete which has among other functionality the following options

Deleting unused files from the default files directory that are not in the file managed table. AKA deleting all the unmanaged files.

Deleting unused files from the whole install that are no longer attached to nodes & the file usage table. AKA deleting all the orphaned files.

Umbra answered 13/5, 2018 at 20:23 Comment(0)
A
2

We recently contributed a module Unmanaged / Unused Files | Manage | Delete

Ambidextrous answered 8/3, 2021 at 1:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.