I'm creating a node programmatically with one image field. Nodes are Created without any problem.

But if I delete the node the file is marked as "used in 0 place" but never deleted (I run the cron).

If I edit the node and delete the file of the image field, the file is still marked as "used in 1 place".

enter image description here

I want the file be deleted instantaneously like if I create the node using the node form.

 * Create a new book from google data
 * @param array $booksData
 * @return \Drupal\Core\Entity\EntityInterface\static
 * @throws Exception
function book_market_create_book_node(Google_Service_Books_Volumes $booksData) {

  // Google_Service_Books_Volumes object automatically iterate, this will get data from the first book
  $bookData = $booksData[0];

  if (empty($bookData['modelData']['volumeInfo']['title'])) {
    throw new Exception('book data are incomplete');

  $bookNode = Node::create([
    'type' => 'book',
    'moderation_state' => 'published',
    'title' => $bookData['modelData']['volumeInfo']['title'],
    'body' => $bookData['modelData']['volumeInfo']['description']

  $imageLink = $bookData['modelData']['volumeInfo']['imageLinks']['smallThumbnail'];

  if (isset($imageLink)) {
    $data = file_get_contents($imageLink);

    $transliterator = new Drupal\Core\Transliteration\PHPTransliteration(NULL, \Drupal::moduleHandler());
    $fileName = $bookData['modelData']['volumeInfo']['title'];
    $fileName = str_replace(' ', '_', $fileName);
    $fileName = $transliterator->transliterate($fileName, 'fr', '_') . '.jpeg';

    $field_cover_settings = $bookNode->field_cover->getDataDefinition()
    $destination = $field_cover_settings['uri_scheme'] . '://' . $field_cover_settings['file_directory'] . '/' . $fileName;
    $destination = \Drupal::token()->replace($destination);

    $file = file_save_data($data, $destination, FILE_EXISTS_RENAME);

    $bookNode->set('field_cover', [
      'target_id' => $file->id(),


  return $bookNode;
  • Have a look at the known issues of Drupal 8. There are several known problems with file usage and nodes. Depending on your situation they might contain useful information. Feb 12, 2017 at 14:27
  • @Neograph734 thanks for the pointer. Perhaps also using file_save_data is creating the file entity independently of the node. But I don't know how to create the file entity "with" the node.
    – gagarine
    Feb 12, 2017 at 20:24
  • Files_save_data indeed does not register usage (if that is what you meant). That is what file_usage_add Is for. Feb 12, 2017 at 20:27
  • @Neograph734 but because I set the node field field_cover with the file entity, drupal is smart enough to register usage, but not to delete the file. What I mean is perhaps I should create the file differently so Drupal understand this file is only used with this node and I don't need it when the node is deleted.
    – gagarine
    Feb 12, 2017 at 20:30

2 Answers 2


Permanent images are not deleted in Drupal 8, read this https://www.drupal.org/node/2891902

To remove the images, you can set $config['file.settings']['make_unused_managed_files_temporary'] = TRUE; in your settings.php. That should be it, it worked for me!

This will remove the permanent files when they are not in use anymore, depending on the time set in /admin/config/media/file-system

For example when you remove a node that contains an image, the image will not be removed at once. The image will be removed when cron executes and make_unused_managed_files_temporary = TRUE.


I think that file will be delete when you run cron. File can't delete because temporary file have time life. You can see code in file_cron.

function file_cron() {
  $age = \Drupal::config('system.file')->get('temporary_maximum_age');
  $file_storage = \Drupal::entityManager()->getStorage('file');

  // Only delete temporary files if older than $age. Note that automatic cleanup
  // is disabled if $age set to 0.
  if ($age) {
    $fids = Drupal::entityQuery('file')
      ->condition('status', FILE_STATUS_PERMANENT, '<>')
      ->condition('changed', REQUEST_TIME - $age, '<')
      ->range(0, 100)
    $files = $file_storage->loadMultiple($fids);
    foreach ($files as $file) {
      $references = \Drupal::service('file.usage')->listUsage($file);
      if (empty($references)) {
        if (file_exists($file->getFileUri())) {
        else {
          \Drupal::logger('file system')->error('Could not delete temporary file "%path" during garbage collection', array('%path' => $file->getFileUri()));
      else {
        \Drupal::logger('file system')->info('Did not delete temporary file "%path" during garbage collection because it is in use by the following modules: %modules.', array('%path' => $file->getFileUri(), '%modules' => implode(', ', array_keys($references))));

You can see line if($age) and line ->condition('changed', REQUEST_TIME - $age, '<'). It's logic when run cron delete file.

And you can go admin/config/media/file-system to see time life of temporary file. Default are 6 hours.

  • You right, majority of the file was deleted. Some still show usage but are "unlinked" from the original entity that was deleted. So their is two issue their.
    – gagarine
    Feb 14, 2017 at 23:49

Your Answer

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

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