0

Using Drupal 9.4. The Media File system is set to Private The Drupal default media type Image is set to private. It now contains hundreds of images. We want to switch only this media type from private to public. We want to keep PDF files private, these are in the Drupal default media type Document.

My process is this. Copy all the images from the private folder over to the public folder, keeping the original sub-directories. Then delete the images from the private folder. Go to > Media Types > Image > Manage fields > Edit image > Field settings - Switch from private to public. Note* It says. There is data for this field in the database. The field settings can no longer be changed. But it accepts the change to public.

Next, update the url in the file managed SQL table, so the url path is public instead of private. This command came from this post. And works great. It updates every file including pdf, word and jpegs. But I just want to update jpeg, png, gif. Can it be modified to only effect a certain filemime? I can run it 1 at a time for each filemime.

UPDATE file_managed SET uri = REPLACE(uri, 'private://', 'public://') where instr(uri, 'private') > 0;

In the SQL File Managed table there is a column filemime. The example data in this is: image/jpeg image/gif application/pdf Would it be something like this to target the filemime

WHERE filemime = 'image/jpeg';

1 Answer 1

2

In general, you should avoid updating tables directly in favor of using Drupal's APIs, so I would not recommend using an SQL query like that.

I had to do the exact opposite of this recently - move files from public to private. The process is the same, here's what I did:

  1. Update the file field's settings to point to the new destination, e.g. from private to public. This will ensure any future files go to the new spot. (You noted that you did this.)

  2. Next, we need to update all existing files. To do this, I wrote a post_update hook to move the files for all of the file entities. (This will be in lieu of the SQL query you're trying to use and you also won't need to manipulate the filesystem directly, i.e. no copying files to different directories, etc.) Note that I did use a batch process, but here's the heart of the code:

$new_file_dir = 'public://my-new-file-directory/';

$mimes = [
  'image/jpeg',
  // etc...
];

// Get the file entity ids for the files with your wanted file mimes.
$file_entity_ids = \Drupal::entityTypeManager()
  ->getStorage('file')
  ->getQuery()
  ->condition('filemime', $mimes, 'IN')
  ->execute();

// Load the file entities.
$file_entities = \Drupal::entityTypeManager()
  ->getStorage('file')
  ->loadMultiple($file_entity_ids);

// Move the files associated with the file entities.
foreach ($file_entities as $file) {
  \Drupal::service('file.repository')
    ->move($file, $new_file_dir . $file->getFilename());
}
17
  • This looks good but it does not fully answer the question. The question seeks also to do this only for certain file types.
    – cilefen
    Jan 10 at 21:20
  • Sure, I guess I can write that code too.
    – sonfd
    Jan 10 at 21:46
  • Thank you @sonfd, I see you added the $mimes variable. I will try this soon and post here again Jan 10 at 22:19
  • I tried it and I get the error [error] Error: Call to undefined method Drupal\Core\Entity\EntityTypeManager::loadMultiple() Jan 11 at 12:31
  • When I hover over loadMultiple, I see Method 'loadMultiple' not found in Drupal\Core\Entity\EntityTypeManagerInterface I think I forgot to add a use a the top of the file Jan 11 at 12:36

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.