Как сохранить файлы в личный каталог?
Я пишу пользовательский модуль, в котором данные записываются в файл, а файл хранится в папке частного каталога.
Для этого я создал частный каталог и назначил ему необходимые разрешения (могу подтвердить, что он доступен для записи, протестировал его, создав новый тип контента из пользовательского интерфейса и добавив файл, загруженный в файл, и способный сохранить загруженный файл в этот каталог). Но моя проблема в том, что я не могу сохранить файл в этот каталог программно.
Я получите сообщение об ошибке с указанием:
Данные не удалось сохранить, поскольку адресат /var/www/html/сайты/имя сайта/файлы/частный/файл.json недействителен. Это может быть вызвано неправильным использованием file_save_data() или отсутствующей оболочкой потока.
Мой личный каталог расположен в каталоге файлов как подкаталог и назван как частный, я настроил его в settings.php и можете просмотреть его в https://example.com/admin/config/media/file-system
конечно, очистил кэш после настройки личного каталога в settings.php .
Я могу сохранить файл в общедоступный каталог, используя следующий код:
$output = Json::encode($data);
$directory = file_default_scheme() . '://userslist';
file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$fileLocation = $directory.'/'.JSON_FILENAME;
$file = file_save_data($output, $fileLocation, FILE_EXISTS_REPLACE);
Но я не могу сохранить в подпапке в общедоступном каталоге, используя следующий код:
$directory = \Drupal::service('file_system')->realpath("public://userslist");
То же самое относится и к частному каталогу:
$directory = \Drupal::service('file_system')->realpath("private://");
Я даже могу сохранять данные, используя следующий код:
$directory = file_default_scheme() . '://private';
Поскольку частный каталог присутствует в качестве подкаталога в общедоступном каталоге, следовательно, путь к общедоступному каталогу назначен вручную выше.
Но не удается сохранить с помощью realpath
который динамически получает путь к частному или общедоступному файловому каталогу.
Может ли кто-нибудь помочь мне решить эту проблему?
Я попробовал функциональность в двух разных системных средах: одна - Linux, а другая - Windows, и я получаю ту же ошибку, что и выше.
Спасибо.
Редактировать 1: Я сделал несколько ошибок и ошибок и получил следующие результаты, но все еще не могу найти правильный способ сохранить файл в личный каталог.
// My private file configuration in settings.php
$settings['file_private_path'] = 'sites/sitename/files/private';
$directory = file_default_scheme() . '://userslist';
dpm($directory); // public://userslist
// File is writable to the directory and can be accessed through browser.
$directory = PrivateStream::basePath(). '://userslist'; ;
dpm($directory); // sites/sitename/files/private://userslist
$directory = PrivateStream::basePath(). '/userslist'; ;
dpm($directory); // sites/sitename/files/private/userslist
$directory = drupal_realpath('public://userslist');
dpm($directory); // /var/www/html/sites/sitename/files/userslist
$directory = \Drupal::service('stream_wrapper_manager')->getViaUri('private://userslist')->getUri();
dpm($directory); // private://userslist
// File is writable to the directory and can't be accessed through browser.
// normally a file which is present in private directory and accessed through browser will have the following url pattern
// https://example.com/sitename/default/files/private/userslist/file.json
// but it has the following pattern.
// https://example.com/sitename/system/files/userslist/file.json
$directory = \Drupal::service('file_system')->realpath(file_default_scheme().'://userslist');
dpm($directory); // /var/www/html/sites/sitename/files/userslist
$directory = \Drupal::service('file_system')->realpath("private://userslist") ;
dpm($directory); // /var/www/html/sites/sitename/files/private/userslist
$directory = \Drupal::service('file_system')->realpath("public://userslist");
dpm($directory); // /var/www/html/sites/sitename/files/userslist
$directory = file_default_scheme() . '://private/userslist';
dpm($directory); //public://private/userslist
3 answers
Ваш код почти готов, на самом деле вам не нужен realpath
. Построение переменной $directory
в виде URI-оболочки потока (т.Е. private://SOME_PATH
) является стандартным способом.
Вы получаете эту ошибку от file_valid_uri()
- который называется
file_save_data()
- и ожидает параметр обертки потока $destination
(без абсолютных/относительных путей).
В общем, я бы посоветовал вам держаться подальше от абсолютных/относительных путей к файлам и использовать синтаксис URI обертки потока, функции, которые вы используете, поддерживают и/или ожидайте их.
Следующий код позволит вам использовать частную файловую систему:
use Drupal\Core\StreamWrapper\PrivateStream;
...
...
$file_save_path_stream_directory = 'private://userslist';
...
...
file_prepare_directory($file_save_path_stream_directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$fileLocation = $file_save_path_stream_directory . '/' . JSON_FILENAME;
$file = file_save_data($output, $fileLocation, FILE_EXISTS_REPLACE);
Удачи!
P.S.: Прочтите эту запись об изменении (https://www.drupal.org/node/2392959 ), содержит важную относительную информацию.
Я согласен с @Стефаносом Петракисом, что вам не нужен реальный путь, потому что file_valid_uri()
сделает уведомление, но $directory = PrivateStream::basePath() . '://userslist';
укажет вам путь к личному файлу, который также не является допустимым uri.
Попробуйте выполнить следующее.
$directory = \Drupal::service('stream_wrapper_manager')->getViaUri('private://userslist')->getUri();
file_prepare_directory($directory, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
$fileLocation = $directory . '/' . JSON_FILENAME;
$file = file_save_data($output, $fileLocation, FILE_EXISTS_REPLACE);
Хотя это старый вопрос, я хотел бы отметить, что сейчас он устарел. Вместо этого мы должны использовать \Drupal::service('file_system')
сейчас.
Как file_prepare_directory
теперь говорится:
function file_prepare_directory(&$directory, $options = FileSystemInterface::MODIFY_PERMISSIONS) {
@trigger_error('file_prepare_directory() is deprecated in Drupal 8.7.0 and will be removed before Drupal 9.0.0. Use \Drupal\Core\File\FileSystemInterface::prepareDirectory(). See https://www.drupal.org/node/3006851.', E_USER_DEPRECATED);
return \Drupal::service('file_system')->prepareDirectory($directory, $options);
}
Пожалуйста, смотрите https://www.drupal.org/node/3006851 для получения дополнительной информации.