I am writing a custom module in which data is written to a file and the file is stored in a private directory folder.
In order to do so I have created a private directory and assigned required permissions to it(can confirm it is writable, tested it by creating a new content type from UI and added a file upload filed and able to save uploaded file to that directory). But my problem is I can't save the file to that directory programmatically.
I get an error stating :
The data could not be saved because the destination /var/www/html/sites/sitename/files/private/file.json is invalid. This may be caused by improper use of file_save_data() or a missing stream wrapper.
My private directory is located in files directory as a subdirectory and named as private, I have configured it in settings.php and can view it in https://example.com/admin/config/media/file-system
of course cleared the cache after configuring the private directory in settings.php.
I can save file into public directory using the following code:
$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);
But I can't save in subfolder in public directory using the following code :
$directory = \Drupal::service('file_system')->realpath("public://userslist");
Same is the case with private directory :
$directory = \Drupal::service('file_system')->realpath("private://");
I can even save data using the following code :
$directory = file_default_scheme() . '://private';
as the private directory is present as a subdirectory in public directory hence assigned manually public directory path above.
But can't save using the realpath
which obtains the private or public file directory path dynamically.
Can anyone help me out to solve the issue?
I tried the functionality in two different system environments one is Linux and other is windows and I get the same error as above.
Thanks.
Edit 1 : I hade made some trail and errors and got the following results but still cant find a correct way to save the file to private directory.
// 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