After upgrading from drupal 6 to 7 I want to turn a public file field into a private. Since it contains data the system does not allow this.

If I go to field settings it says: "There is data for this field in the database. The field settings can no longer be changed."

Is there a way to do this?

Comments

johnnyfofo’s picture

I think that this is a legitimate question.

With an image field which already had numerous entries (data uploaded through it) I was able to change from public to private...

One can also understand if the files themselves don't move and some database search-and-replace is needed for previous uploads, but it would be nice if there was a workaround for making public filefields private.

Ground Unit’s picture

Subscribe!

Have an urgent need to convert public file field to private. Is there any solution?

A Romka’s picture

yeah wondering the same, "private / public" option is disabled for the field .. how to move from one to another?

A Romka’s picture

ok, nevermind, figured it out.

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

done.

Chandan Chaudhary’s picture

I belive apart from the respective data table we need to also take a backup for the revision table in the above mention case field_revision_field_attachments

Need Drupal help?
Reach me

Acquia Certified Developer

Backend Frontend and DevOps.

Slovak’s picture

Excellent advice. Make sure you have http://drupal.org/project/filefield_paths installed.

emanaton’s picture

Incorporating the various bits of knowledge in this thread with some knowhow, here's my recipe for making this happen:

1. make a back up of the file field data tables
drush sqlq "CREATE TABLE field_data_field_[FIELD NAME]_bak AS SELECT * FROM field_data_field_[FIELD NAME];"
drush sqlq "CREATE TABLE field_revision_field_[FIELD NAME]_bak AS SELECT * FROM field_revision_field_[FIELD NAME];"

2. empty file field data tables
drush sqlq "TRUNCATE TABLE field_data_field_[FIELD NAME];"
drush sqlq "TRUNCATE TABLE field_revision_field_[FIELD NAME];"

3. in the file field settings in drupal the option to change that field to private is now available; do so and save the field

4. copy all data from the temp backup tables back in to the real tables
drush sqlq "INSERT INTO field_data_field_[FIELD NAME] SELECT * FROM field_data_field_[FIELD NAME]_bak;"
drush sqlq "INSERT INTO field_revision_field_[FIELD NAME] SELECT * FROM field_revision_field_[FIELD NAME]_bak;"

5. enable the filefield_paths module (if it’s not already)
drush en -y filefield_paths

6. in the “FILE (FIELD) PATH SETTINGS” area of the file field settings in drupal, select the “Retroactive update” option and save; it will move all the files to the right place in file system and update the db to the new path (which may take a little while)

7. delete the temp storage tables
drush sqlq "DROP TABLE field_data_field_[FIELD NAME]_bak;"
drush sqlq "DROP TABLE field_revision_field_[FIELD NAME]_bak;"

bdupls’s picture

I switched my datatables path on Drupal commons 7 site back to public as d7 commons wasn't allow members of a community to view the downloads. I ran your code but my links are still showing system/files. I tried to set the path with the following but it seems D7 doesn't use 'files' table.
UPDATE files SET filepath = REPLACE(filepath,'private/','/sites/default/files');
Can you assist. Much appreciated.

bdupls’s picture

I switched my datatables path on Drupal commons 7 site back to public as d7 commons wasn't allow members of a community to view the downloads. I ran your code but my links are still showing system/files. I tried to set the path with the following but it seems D7 doesn't use 'files' table.
UPDATE files SET filepath = REPLACE(filepath,'private/','/sites/default/files');
Can you assist. Much appreciated.

Greenstack’s picture

Here's a small script that I wrote to help automate the process (useful if you have to change more than one field)

#!/bin/bash
# Make a back up of the file field data tables
drush sqlq "CREATE TABLE field_data_field_$1_bak AS SELECT * FROM field_data_field_$1;"
drush sqlq "CREATE TABLE field_revision_field_$1_bak AS SELECT * FROM field_revision_field_$1;"

#empty file field data tables
drush sqlq "TRUNCATE TABLE field_data_field_$1;"
drush sqlq "TRUNCATE TABLE field_revision_field_$1;"

echo "In the file field settings in Drupal, the option to change the field $1 to"
echo "private is now available. Do so and save the field."

read -p "Once finished, press Enter to continue."

#copy all data from the temp backup tables back in to the real tables

drush sqlq "INSERT INTO field_data_field_$1 SELECT * FROM field_data_field_$1_bak;"
drush sqlq "INSERT INTO field_revision_field_$1 SELECT * FROM field_revision_field_$1_bak;"

echo "In the FILE (FIELD) PATH SETTINGS are of the file field settinsg in Drupal, select the 'Retroactive Upgrade' option and save; it will move all the files to the right place in the file system and update the db to the new path (which may take a little while)."
read -p "Once you have completed this step, press Enter to continue."

#delete the temp storage tables
drush sqlq "DROP TABLE field_data_field_$1_bak;"
drush sqlq "DROP TABLE field_revision_field_$1_bak;"

Alternatively, here's the GitHub gist for the script.

bburg’s picture

I am assuming this requires the File Field Paths module for the "Retroactive Upgrade" option?

Metatag should be in core.

ñull’s picture

In Drupal 6 I was too inpatient to wait for the Drupal 7's feature of both public and private. I used the .htaccess to rewrite queries to system/files. This way I could determine which folders need to be private.

But how do you migrate that to Drupal 7? It took me the following steps:

  1. Enable private system file and set private path equal to public
    drush vset file_default_scheme "private"
    drush sqlq "UPDATE variable f, variable t SET t.value=f.value WHERE f.name='file_public_path' AND t.name='file_private_path' "
  2. Correct file_managed uri to private://
    drush sqlq "UPDATE file_managed SET uri=REPLACE(uri,'public://','private://') where uri LIKE 'public://%'
  3. Backup table field_data_upload and truncate it.
  4. Change the setting to private in /admin/structure/types/manage/<your-content-type>/fields/<your-attachment-field>/field-settings</your-attachment-field></your-content-type>
  5. Restore table field_data_upload from backup
  6. Set .htaccess in files path
    SetHandler Drupal_Security_Do_Not_Remove_See_SA_2006_006 Options None Options +FollowSymLinks <ifmodule mod_rewrite.c=""> RewriteEngine On RewriteBase / RewriteRule ^(.*)$ index.php?q=system/files/$1 [L] </ifmodule>
  7. Disable rewrite in folders that shouldn't be private (css, js, language etc)
    <ifmodule mod_rewrite.c=""> RewriteEngine off </ifmodule>

     

rivimey’s picture

Many thanks for this procedure....

... and you do need to flip both file data and file revision tables.

For clarity, the retrospective update option is a checkbox in the main edit page for the field, within a File (Field) Paths collapsible container.

R.

mmiguel2014’s picture

So the problem is that we are able to move all the files to the private folder but all the previous nodes still contain the old URLs of those files.

Is there a method/module which can enable us to change those URLs?

Thx for any response.

hgoto’s picture

If I understand it correctly, the approach with the filefield_paths module stated above doesn't work at the moment until the following issue gets fixed.

https://www.drupal.org/node/2895035

eigentor’s picture

I tried the approach described above and the retroactive update worked. I used Filefield Paths 7.x-1.0. The bug report you linked appears to refer to the dev version, which is newer.

alexTC’s picture

highly recommended

someshver’s picture

Solution for drupal 8

$storage = \Drupal\field\Entity\FieldStorageConfig::loadByName('(Type OF Entity)', '(Name Of field)');
$storage->setSetting('uri_scheme', 'private');
$storage->save();

* Type Of entity :- media, paragraph, file etc
* Name Of field :- field_media_image etc

andresmabg’s picture

Hi, i´m new at this and got the same problem... how or where do i write that? settings.php?