Drupal - How to make existing public files private?

Thanks a lot for the answers! FileField Paths definitely is the way to go.

  1. Update the file field's field storage to handle private files.
  2. Run FileField Paths' Retroactive update on your content type's file field.

Step 1. can be accomplished from within hook_update_N (if you use configuration management do that locally and then export the updated configuration and deploy the resulting *.yml):

$field_type = 'file';
$field_name = 'field_file';

if (!$field_storage_configs = \Drupal::entityManager()
  ->getStorage('field_storage_config')
  ->loadByProperties(['type' => $field_type])) {
  return;
}

foreach ($field_storage_configs as $field_storage) {
  // Note: These settings apply to the field_file field everywhere it is
  // used.
  if ($field_storage->getName() == $field_name) {
    $field_storage->setSetting('uri_scheme', 'private');
    $field_storage->enforceIsNew(FALSE);
    $field_storage->save();
  }
}

Alternatively, follow the manual config update and reimport as suggested in the question.


Step 2. is to go to your file field's edit screen and fire the Retroactive update upon saving the form:

enter image description here


It's quite simple, I tested this myself and it works.

1) With PHPMyAdmin or some DB managing application, you'll need to look at node__field_NAME that has your files. Record all the field_NAME_target_id numbers that belong to your content type.

2) Go to to file_managed table.

3) Export table as .sql file

4) Open .sql file with some text editing app. Rename all public:// to private:// for the ones that have the fid number that you recorded.

5) Import .sql and override table file_managed. OR you could clear the table and then import.

6) Move the files to the private folder.

  • Important: make sure that it has the same parent folder structure. If it was previously under /files/2018-06/some.jpg, in private it needs to be /private/2018-06/some.jpg

    • Also, no need to move image style image files, these will get auto created. Thus, you only need to grab the original.

7) Flush all caches.


I'm sure you could use SQL query to do 1 to 5. Basically all you gotta do is update the specific values of the uri column in the field_managed table.


I did this for Drupal 7, but haven't tried it in Drupal 8.

I believe that it should work similarly since there is already a D8 release for the required module: FileField Paths. I first installed and enabled the module before following the steps below:

just in case someone is looking to do this, here are the steps:

  1. backup your site and db
  2. copy the table for your field to make a backup (in my case i copied: field_data_field_attachments to field_data_field_attachments_bk)
  3. empty table field_data_field_attachments
  4. go to drupal and the option to change the file system should be available, so change it
  5. copy all data from field_data_field_attachments_bk back to field_data_field_attachments
  6. go to drupal, select your content type, select your file field, in file path settings select retroactive update
  7. click save and it will move all your files to the right place in file system and update your db to the new path

— A Romka

Full thread

Tags:

Files

8