web-dev-qa-db-fra.com

Comment enregistrer des fichiers dans un répertoire privé?

J'écris un module personnalisé dans lequel les données sont écrites dans un fichier et le fichier est stocké dans un dossier de répertoire privé.

Pour ce faire, j'ai créé un répertoire privé et lui ai attribué les autorisations requises (peut confirmer qu'il est accessible en écriture, le tester en créant un nouveau type de contenu à partir de l'interface utilisateur et ajouter un fichier téléchargé et pouvoir enregistrer le fichier téléchargé dans ce répertoire) . Mais mon problème est que je ne peux pas enregistrer le fichier dans ce répertoire par programme.

Je reçois une erreur indiquant:

Les données n'ont pas pu être enregistrées car la destination /var/www/html/sites/sitename/files/private/file.json n'est pas valide. Cela peut être dû à une mauvaise utilisation de file_save_data () ou à un wrapper de flux manquant.

Mon répertoire privé est situé dans le répertoire des fichiers en tant que sous-répertoire et nommé privé, je l'ai configuré dans settings.php et je peux le voir dans https://example.com/admin/config/media/file-system bien sûr, effacé le cache après avoir configuré le répertoire privé dans settings.php.

Je peux enregistrer le fichier dans le répertoire public en utilisant le code suivant:

    $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);

Mais je ne peux pas enregistrer dans le sous-dossier du répertoire public en utilisant le code suivant:

    $directory = \Drupal::service('file_system')->realpath("public://userslist");

Il en va de même avec le répertoire privé:

    $directory = \Drupal::service('file_system')->realpath("private://");

Je peux même enregistrer des données en utilisant le code suivant:

    $directory = file_default_scheme() . '://private';

car le répertoire privé est présent en tant que sous-répertoire dans le répertoire public et donc assigné manuellement le chemin du répertoire public ci-dessus.

Mais ne peut pas enregistrer en utilisant realpath qui obtient le chemin du répertoire de fichiers privé ou public de manière dynamique.

Quelqu'un peut-il m'aider à résoudre le problème?

J'ai essayé la fonctionnalité dans deux environnements système différents, l'un est Linux et l'autre est Windows et j'obtiens la même erreur que ci-dessus.

Merci.

Edit 1: Je n'ai pas fait de traces et d'erreurs et j'ai obtenu les résultats suivants, mais je n'arrive toujours pas à trouver un moyen correct d'enregistrer le fichier dans un répertoire privé.

    // 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
1
miststudent2011

Votre code est presque là, vous n'avez pas vraiment besoin de realpath. La construction de la variable $directory En tant qu'URI d'encapsuleur de flux (c'est-à-dire private://SOME_PATH) Est la méthode standard.

Vous obtenez cette erreur de file_valid_uri() - qui est appelée par file_save_data() - et attend un wrapper de flux $destination (pas de chemin absolu/relatif).

En général, je vous suggère de vous tenir à l'écart des chemins de fichiers absolus/relatifs et d'utiliser la syntaxe URI des wrappers de flux, les fonctions que vous utilisez et/ou les attendez.

Le code suivant vous permettra d'utiliser le système de fichiers privé:

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);    

Bonne chance!

P.S .: Lisez cet enregistrement de changement ( https://www.drupal.org/node/2392959 ), contient des informations relatives importantes.

2

Je suis d'accord avec @Stefanos Petrakis, vous n'avez pas besoin de realpath car, file_valid_uri() fera la remarque, mais $directory = PrivateStream::basePath() . '://userslist'; vous donnera le chemin du fichier privé ce n'est pas non plus un uri valide.

Essayez ce qui suit.

  $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);
1
berramou