IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage PHP Discussion :

Envoyer tout un fichier dans OUTPUT en utilisant des commandes systèmes


Sujet :

Langage PHP

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut Envoyer tout un fichier dans OUTPUT en utilisant des commandes systèmes
    Bonjour,
    Afin de pouvoir lire le contenu d'un fichier sur des images montées je dois utiliser des commandes dos/powershell.
    J'ai trouvé cette méthode :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    passthru("type le_fichier_à_lire",$retour);
    qui retourne tout le contenu du fichier vers la sortie. Mais cette méthode ralentit la lecture à 400 ko/s au lieu de 60 Mo/s et parfois la lecture échoue sans raison il faudrait trouver une méthode pour relancer la lecture mais comment récupérer le code de sortie et savoir si la lecture s'est déroulée normalement ?

    Existe t il d'autres méthodes permettant d'arriver au même résultat ? powershell et get-content, mais comment l'utiliser avec passthru() sans ajouter des caractères indésirables sur la sortie ?
    rq :
    fopen(), readfile() ne marchent pas dans mon cas.

  2. #2
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 672
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 672
    Par défaut
    regardez dans les exemples de code de la page suivante, il y a des exemples d'utilisation de données retournées par des programmes :
    https://www.php.net/manual/fr/function.popen.php

    si cela ne règle pas le problème de vitesse, peut-être que vous pouvez lancer un programme en arrière-plan qui enregistre le fichier dans un répertoire temporaire et ensuite le code php lira ce fichier temporaire.

  3. #3
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    Bonjour,,

    Merci pour ces conseils. A priori je n'utilise que php donc je ne prévoit pas d'utiliser un autre programme qui télécharge le fichier sur un dossier temp.

    Je viens de tester popen et étant donné le contexte du système de fichier (lecture d'image montée) j'ai une erreur qui apparaît permettant peut être de mieux comprendre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    popen("type mon_fichier",'rb');
    me renvoit :

    Le processus a tenté d’écrire sur un canal inexistant.
    Donc ça ne marche pas du tout alors que le fichier peut être ouvert directement en tapant le chemin complet sous dos.

  4. #4
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    J'ai essayé la fonction system(). Et pour l'instant celle ci donne les meilleurs résultats :
    -la vitesse est bien supérieure (entre 2 Mo/s et 10 Mo/s et même plus
    -la commande retourne bien le fichier lorsqu'on l'exécute 2 fois en général (2 appels du script php)

    Je pense aussi que la commande type peut poser problème parfois dans le contexte de fichiers montés.

    En essayant des commandes powershell cela me semble plus rapide et cela fonctionne à priori tout le temps :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Get-content mon_fichier
    par contre je n'arrive pas à utiliser powershell de façon équivalente à
    system();

    Existe t il un moyen ? (sans passer par le programme powershell.exe )

  5. #5
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    J'arrive à utiliser Get-content mon_fichier et récupérer la sortie par php, mais dans le cas d'une image par exemple le fichier qui est envoyé dans l'output après appel de system() contient des erreurs : mon lecteur indique que le fichier n'est pas une image puisqu'il commence par 0xc3 0xbf comme si powershell ajoutait des caractères avant d'envoyer le contenu du fichier
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    powershell -Noninteractive -nologo -command "get-content monfichier"
    Comment éviter cela ?

  6. #6
    Expert confirmé
    Avatar de mathieu
    Profil pro
    Inscrit en
    Juin 2003
    Messages
    10 672
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2003
    Messages : 10 672
    Par défaut
    C3BF est la représentation en utf-8 du caractère FF. peut-être qu'un fichier php a un entête de ce genre ? les anciens éditeurs utilisaient des caractères spéciaux en début de fichier pour indiquer l'encodage utilisé.
    une autre possibilité est qu'il y ait quelque part une conversion d'encodage, ce qui ne devrait pas avoir avec un fichier binaire.

  7. #7
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    D'après ce que je comprends powershell.exe ne permet pas de retourner des données binaires, mais du texte il n'agit pas sur le système d'exploitation comme le fait dos associant des extensions à des programmes... donc dans mon cas powershell ne peut pas être utilisé (simplement).

  8. #8
    Nb
    Nb est déconnecté
    Membre éprouvé
    Profil pro
    Inscrit en
    Décembre 2003
    Messages
    163
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2003
    Messages : 163
    Par défaut
    Je ne suis pas sur de comprendre le probleme.
    Qu essaie-tu de faire exactement.
    Une page qui lit un fichier et affiche son contenu?

    Par curiosité quelle cintrainte empeche l utilisation de fopen?

  9. #9
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    Bonjour,
    ce que je constate fopen() ne fonctionne pas car les fichiers sont sur une image WIM montée dans un dossier windows. J'obtiens false avec fopen même en insistant.
    Seules les commandes dos semblent pouvoir accéder aux fichiers sans problème (ex robocopy, type...).
    Je ne trouve aucune info là dessus donc je cherche des alternatives.
    J'ai posé la question sur le forum windows peut être qu'il y a une explication. Les fichiers montés sont bien accessibles par l'exporateur windows par ex et apparaissent comme s'ils étaient dans le dossier monté, ce dossier peut être utilisé normalement en lecteur écriture. fopen fonctionne si j'ai ouvert l'exporateur et le fichier en question préalablement sinon il ne trouve pas le fichier alors que IF EXIST le trouve bien tout le temps.
    J'en suis au stade où j'arrive à ouvrir le fichier tout le temps à condition d'exécuter la commande system("type mon fichier") au moins 2 fois. Je cherche une solution pour n'exécuter qu'une fois tout en ne trouvant pas d'explications à tout cela. Parfois ça fonctionne du premier coup mais je pense que c'est parce que j'avais déjà chargé le fichier quelques heures avant.

  10. #10
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 518
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 518
    Par défaut
    Bonjour ! Je comprends tout à fait votre frustration. C'est une situation assez particulière et il est vrai que les informations à ce sujet sont rares.

    Ce que vous décrivez avec fopen() et les images WIM montées semble indiquer un problème lié à la façon dont PHP (ou plus précisément, l'environnement sous lequel PHP s'exécute) interagit avec le système de fichiers virtuel créé par le montage WIM. Voici quelques pistes pour comprendre et potentiellement résoudre votre problème :

    Comprendre le Comportement

    Il est intéressant de noter que les commandes DOS comme robocopy ou type fonctionnent, et que l'Explorateur Windows y a également accès. Cela suggère que le problème ne vient pas de l'accessibilité du fichier en soi, mais plutôt de la manière dont PHP tente d'y accéder.

    Quand vous dites que fopen() fonctionne après avoir ouvert le fichier dans l'Explorateur ou après avoir exécuté system("type mon fichier") plusieurs fois, cela me fait penser à un problème de :

    Mise en cache ou indexation : Il est possible que le système de fichiers ou PHP lui-même ait besoin d'une sorte de "déclencheur" pour reconnaître que les fichiers dans le point de montage WIM sont prêts à être manipulés par des applications de plus haut niveau comme PHP. L'Explorateur ou la commande type pourraient jouer ce rôle en forçant le système à "actualiser" sa vue du point de montage.

    Permissions ou contexte utilisateur : Bien que l'Explorateur et les commandes DOS aient accès, il est possible que le serveur web (Apache, Nginx, ou PHP-FPM) sous lequel votre script PHP s'exécute n'ait pas les mêmes droits ou le même contexte d'exécution que votre session utilisateur interactive. Cependant, si cela fonctionnait après un "type", cela semble moins probable comme cause principale, mais cela vaut la peine d'être vérifié.

    Verrouillage de fichiers (moins probable ici) : Un fichier peut être verrouillé par une autre application, mais étant donné que type fonctionne, c'est peu probable que ce soit la cause première.

    Alternatives et Solutions Possibles

    Puisque fopen() est capricieux, il faut envisager des approches qui contournent cette limitation ou qui forcent la reconnaissance du fichier.

    1. Utiliser file_get_contents() ou file_put_contents()
    Si vous avez besoin de lire ou écrire le contenu entier d'un fichier, ces fonctions PHP sont souvent plus robustes et peuvent parfois contourner des problèmes de fopen() car elles gèrent l'ouverture et la fermeture du fichier en une seule opération.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    $chemin_fichier = "C:\\chemin\\vers\\votre\\dossier_monte\\mon_fichier.txt";
     
    // Tentative de lecture
    $contenu = file_get_contents($chemin_fichier);
     
    if ($contenu !== false) {
        echo "Contenu du fichier : " . $contenu;
    } else {
        echo "Impossible de lire le fichier avec file_get_contents().";
    }

    2. Exploiter les Commandes DOS via system() ou exec()
    Puisque les commandes DOS fonctionnent de manière fiable, vous pourriez les utiliser pour interagir avec les fichiers, puis manipuler le résultat en PHP.

    Lecture de fichiers : Pour lire le contenu, vous pouvez rediriger la sortie de type vers un fichier temporaire, puis lire ce fichier temporaire avec PHP.
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    $chemin_fichier_source = "C:\\chemin\\vers\\votre\\dossier_monte\\mon_fichier.txt";
    $chemin_fichier_temp = "C:\\chemin\\vers\\un\\dossier_temp\\temp_file.txt"; // Assurez-vous que ce dossier est inscriptible
     
    // Exécuter la commande type et rediriger la sortie vers un fichier temporaire
    // Cette commande est exécutée une seule fois.
    $command = "type \"" . $chemin_fichier_source . "\" > \"" . $chemin_fichier_temp . "\"";
    system($command, $return_var);
     
    if ($return_var === 0) { // La commande s'est exécutée sans erreur
        $contenu = file_get_contents($chemin_fichier_temp);
        if ($contenu !== false) {
            echo "Contenu du fichier via type : " . $contenu;
        } else {
            echo "Impossible de lire le fichier temporaire.";
        }
        unlink($chemin_fichier_temp); // Supprimer le fichier temporaire
    } else {
        echo "Erreur lors de l'exécution de la commande type.";
    }
    Cette méthode résoudrait votre problème de devoir exécuter type deux fois, car la sortie est directement capturée et écrite une seule fois dans un fichier accessible par PHP.

    Écriture de fichiers : Pour écrire, vous pouvez écrire le contenu en PHP dans un fichier temporaire non monté, puis utiliser copy ou move via system() pour le déplacer dans le point de montage WIM.

    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    $chemin_cible = "C:\\chemin\\vers\\votre\\dossier_monte\\nouveau_fichier.txt";
    $contenu_a_ecrire = "Ceci est le nouveau contenu.";
    $chemin_fichier_temp_local = "C:\\chemin\\vers\\un\\dossier_temp\\temp_local_file.txt";
     
    file_put_contents($chemin_fichier_temp_local, $contenu_a_ecrire);
     
    $command = "copy /Y \"" . $chemin_fichier_temp_local . "\" \"" . $chemin_cible . "\"";
    system($command, $return_var);
     
    if ($return_var === 0) {
        echo "Fichier écrit avec succès via copy.";
    } else {
        echo "Erreur lors de l'écriture du fichier via copy.";
    }
    unlink($chemin_fichier_temp_local);
    3. Vérifier les Permissions du Serveur Web
    Même si vous avez constaté des améliorations après l'Explorateur, assurez-vous que l'utilisateur sous lequel PHP s'exécute (par exemple, IUSR pour IIS, ou l'utilisateur configuré pour Apache) a les droits de lecture/écriture sur le dossier de montage WIM. C'est une vérification de base qui peut parfois résoudre des problèmes inattendus.

    4. La Piste de la "Double Exécution"
    Le fait que system("type mon fichier") ait besoin d'être exécuté deux fois pour que fopen fonctionne me fait vraiment penser à un problème de cache ou d'initialisation lente du système de fichiers virtuel. La première exécution pourrait "réveiller" le montage, et la seconde confirmerait son accessibilité.

    L'approche consistant à utiliser type pour rediriger la sortie vers un fichier temporaire (comme décrit plus haut) est la meilleure solution pour cela, car vous n'exécutez la commande qu'une seule fois et le reste de la manipulation se fait sur un fichier local non impacté par le montage WIM.

    En Résumé
    Votre meilleure option pour le moment, étant donné les limitations de fopen() avec votre montage WIM, est d'utiliser les commandes DOS (type, copy, move) via system() ou exec() en PHP. Cela vous permet de tirer parti de ce qui fonctionne déjà (les commandes DOS) et de contourner les caprices de PHP dans cet environnement spécifique.

    Si les performances sont un souci pour des fichiers très volumineux, le compromis serait d'extraire les fichiers du WIM vers un emplacement temporaire standard avant de les manipuler avec PHP, puis de les réintégrer. Cependant, cela ajoute de la complexité.

    Avez-vous essayé la méthode de redirection de type vers un fichier temporaire ? Cela devrait vous permettre de résoudre votre problème de "double exécution".

  11. #11
    Membre éclairé
    Homme Profil pro
    Développeur Web
    Inscrit en
    Avril 2014
    Messages
    266
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Avril 2014
    Messages : 266
    Par défaut
    Bonjour Toufik83,

    Merci pour toutes ces explications ou pistes de recherches. J'ai déjà pas mal avancé dans le diagnostic qui n'est pas évident comme vous le reconnaissez, pour moi vus les tests réalisés (très nombreux) ce qui semble coincer provient plus de l'environnement apache/php, sachant qu'en fait le système en lui même ne limite rien à ce niveau là : en utilisant les commandes dos (type mon fichier) les fichiers sont bien lus et transmis vers la sortie du programme php comme souhaité et ceci en mode cli ou en mode module apache php (le mode cli est moins vérouillé donc est un meilleur test pour savoir ce qui coince).

    Comme apache+php fonctionne à partir du moment où j'exécute le code au moins 2 fois (rafraîchissement page), le problème ne vient très certainement pas des droits d'accès, sécurités système.... mais plutôt d'une configuration liée soit à windows (indexation comme vous le dites) ou à apache (latence, cache, buffer, retry...) puisqu'en effet en mode cli d'après mes tests si j'exécute ce code php :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    		$commande="chcp 65001 > NULL & type \"".$nom_fichier_ou_data."\"";
    			system($commande);
    en tapant cette ligne de commande :

    php programme_transfert_fichier.php > "mon_fichier_copié.zzz"
    j'obtiens bien une copie du fichier $nom_fichier_ou_data sans aucune erreur et du premier coup.


    Le problème n'existe que pour cela. Puisque pour créer un fichier ça ne pose aucun problème avec php et apache+php.

    Concernant les solutions possibles :
    J'ai pensé à faire une boucle en vérifiant le retour de system() ou exec() ou procopen() ou .... ou .... ou.................... (nombre d'octets, dernière ligne output, ....) mais rien ne marche la boucle en mode cli ne sert à rien, et en mode apache+php je ça échoue et soit la boucle ne se termine pas, soit apache ou le client ferme la connexion et donc appeler 2 fois system dans le même programme ne marche pas de façon évidente. J'ai aussi essayé quelque chose comme cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    system("php programme_transfert_fichier.php");
    en me disant que la première exécution fonctionnera (mode cli) et que la deuxième exécution fonctionnera quelque soit le mode.

    Mais ça ne donne rien sauf en mode cli où ça marche aussi (même si ça marchait c'est pas top niveau complexité mais pourquoi pas).

    J'ai aussi essayé la la méthode SplFileObject de php qui est récente et très complet pour manipuler les fichiers mais c'est comme fopen.

    file_get_contents() ne marche pas mieux (ni en mode cli ni en mode apache+php) après 3 essais :

    PHP Warning: file_get_contents(C:\...monfichier...ccc): Failed to open stream: No such file or directory in C:\...\...\.fichier.inc.php on line 713

    si j'exécute system("type mon fichier") juste derrière en mode cli ça marche du premier coup.


    Je n'a pas essayé le système de fichiers temporaires, il me semble avant d'en arriver là qu'il est préférable de développer le code php qui permettrait d'extraire le fichier directement depuis l'image (et non le dossier monté) cela irait plus vite, évite d'user les disques et de mobiliser beaucoup de ressources lorsque les fichiers sont très gros.
    Il y a une autre solution qui consiste à créer un serveur de fichiers php qui reçoit des requêtes client, charge le fichier et le transmets au client, du coup tout passe par la mémoire vive. Sachant que cela restera nécessaire que si le fichier et le script n'ont jamais été exécutés sur le serveur apache ; le reste du temps fopen() fonctionne (comme dit plus précédemment).
    Il me semble peut être encore possible d'y arriver en paramétrant apache/php un peu mieux que ce que j'ai fait je pense notamment :
    -aux entêtes http
    -aux fichiers temporaires php ou apache
    -aux fonctions php autorisées
    -...
    -est il possible de rediriger vers une page web virtuelle temporaires (sous apache) qui pointe vers le fichier demandé sans passer par l'exécution de system() avec php (fonctionnement de base du serveur web) ?
    -...

  12. #12
    Expert confirmé Avatar de Toufik83
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2012
    Messages
    2 518
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : Maroc

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Janvier 2012
    Messages : 2 518
    Par défaut
    Bonjour,
    Citation Envoyé par xounet Voir le message
    -est il possible de rediriger vers une page web virtuelle temporaires (sous apache) qui pointe vers le fichier demandé sans passer par l'exécution de system() avec php (fonctionnement de base du serveur web) ?
    Oui, il est tout à fait possible de rediriger vers une page web "virtuelle" temporaire sous Apache qui pointe vers un fichier demandé, sans passer par l'exécution de system() en PHP. Le fonctionnement de base du serveur web Apache et de PHP permet plusieurs approches pour cela.

    Voici les principales méthodes, en privilégiant celles qui n'utilisent pas system():

    1. Utilisation de mod_rewrite (recommandé pour Apache)
    mod_rewrite est le module le plus puissant et le plus couramment utilisé pour la réécriture d'URL dans Apache. Il vous permet de mapper des requêtes HTTP vers des fichiers ou des scripts internes sans que l'utilisateur ne voie la modification de l'URL dans son navigateur (réécriture interne) ou en effectuant une redirection visible (code HTTP 3xx).

    Comment ça marche :

    • Vous définissez des règles de réécriture dans le fichier de configuration Apache (httpd.conf ou un fichier de configuration de VirtualHost) ou dans un fichier .htaccess.
    • Ces règles analysent l'URL demandée par le client.
    • Si l'URL correspond à un motif, mod_rewrite la transforme en une autre URL ou un chemin de fichier sur le serveur.

    Exemple de redirection "virtuelle" avec mod_rewrite :

    Supposons que vous ayez un fichier temporaire /path/to/your/temp_file.pdf et que vous vouliez le rendre accessible via une URL "virtuelle" comme /rapport_temp.pdf.

    Dans votre .htaccess (ou configuration Apache) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    RewriteEngine On
    RewriteRule ^rapport_temp.pdf$ /path/to/your/temp_file.pdf [L]
    Explication :

    • RewriteEngine On: Active le moteur de réécriture.
    • ^rapport_temp.pdf$: C'est le motif de l'URL demandée. ^ et $ ancrent la correspondance au début et à la fin de la chaîne, garantissant que seule cette URL exacte est ciblée.
    • /path/to/your/temp_file.pdf: C'est le chemin réel vers le fichier sur le système de fichiers du serveur.
    • [L]: Le drapeau "Last" (Dernière) indique à mod_rewrite d'arrêter le traitement des règles si celle-ci correspond.


    Avec cette configuration, si un utilisateur accède à http://votre-domaine.com/rapport_temp.pdf, Apache servira le fichier /path/to/your/temp_file.pdf directement, sans que le PHP n'ait besoin d'intervenir via system(). L'URL dans la barre d'adresse du navigateur restera /rapport_temp.pdf.

    Pour une page "virtuelle" temporaire, vous pouvez même générer le nom du fichier temporaire en PHP, puis créer une règle de réécriture dynamique (par exemple, en écrivant temporairement dans un .htaccess ou en utilisant des règles plus complexes avec des bases de données si votre fichier est généré dynamiquement). Cependant, pour un fichier existant et temporaire, mod_rewrite est idéal.

    2. Utilisation de PHP pour servir le fichier directement
    Bien que vous ayez spécifié "sans passer par l'exécution de system() avec PHP", il est important de noter que PHP peut servir des fichiers sans utiliser system(). C'est le moyen le plus courant et le plus sûr de gérer les téléchargements ou l'affichage de fichiers générés dynamiquement ou stockés en dehors du DocumentRoot d'Apache.

    Comment ça marche :

    • Un script PHP est appelé (par exemple, serve_file.php?id=123).
    • Ce script PHP détermine le chemin réel du fichier à servir.
    • Il lit le fichier (ou en génère le contenu) et envoie les en-têtes HTTP appropriés (comme Content-Type, Content-Length, Content-Disposition).
    • Il "passe" le contenu du fichier directement à la sortie HTTP.


    Exemple en PHP (sans system()):
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    $fileId = $_GET['id'] ?? null;
     
    if (!$fileId) {
        header("HTTP/1.0 400 Bad Request");
        exit("ID de fichier manquant.");
    }
     
    // Exemple : Vous déterminez le chemin réel du fichier basé sur l'ID
    // Assurez-vous de valider et de nettoyer $fileId pour éviter les traversées de répertoire !
    $filePath = '/path/to/your/temporary/files/' . basename($fileId) . '.pdf'; // Utilisez basename pour la sécurité
     
    if (!file_exists($filePath)) {
        header("HTTP/1.0 404 Not Found");
        exit("Fichier non trouvé.");
    }
     
    // Définir les en-têtes appropriés
    header('Content-Type: application/pdf'); // Ou le type MIME correct du fichier
    header('Content-Length: ' . filesize($filePath));
    header('Content-Disposition: inline; filename="' . basename($filePath) . '"'); // 'inline' pour afficher dans le navigateur, 'attachment' pour télécharger
     
    // Lire et afficher le contenu du fichier
    readfile($filePath);
     
    exit();

    Dans ce cas, l'URL serait http://votre-domaine.com/serve_file....n_fichier_temp. C'est une page PHP qui agit comme un proxy pour le fichier.

    3. X-Sendfile (Module Apache mod_xsendfile)
    Si vous utilisez PHP pour déterminer quel fichier doit être servi, mais que vous voulez qu'Apache se charge de la transmission réelle du fichier (ce qui est souvent plus performant pour les gros fichiers car Apache peut gérer le flux plus efficacement), vous pouvez utiliser mod_xsendfile.

    Comment ça marche :

    • Votre script PHP détermine le chemin absolu du fichier.
    • Au lieu de lire et d'envoyer le fichier lui-même, PHP envoie un en-tête HTTP spécial X-Sendfile avec le chemin du fichier.
    • Le module mod_xsendfile d'Apache intercepte cet en-tête et sert le fichier directement au client.


    Exemple en PHP avec X-Sendfile :

    D'abord, vous devez vous assurer que mod_xsendfile est installé et activé sur votre serveur Apache. Ensuite, configurez-le (par exemple, dans httpd.conf ou un VirtualHost) :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    # Dans httpd.conf ou le VirtualHost
    XSendFile On
    XSendFilePath /path/to/your/temporary/files/ # Répertoire où se trouvent vos fichiers
    Ensuite, dans votre script PHP :
    Code php : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // serve_file_xsendfile.php
     
    $fileId = $_GET['id'] ?? null;
     
    if (!$fileId) {
        header("HTTP/1.0 400 Bad Request");
        exit("ID de fichier manquant.");
    }
     
    $filePath = '/path/to/your/temporary/files/' . basename($fileId) . '.pdf';
     
    if (!file_exists($filePath)) {
        header("HTTP/1.0 404 Not Found");
        exit("Fichier non trouvé.");
    }
     
    // Définir les en-têtes appropriés
    header('Content-Type: application/pdf');
    header('Content-Disposition: inline; filename="' . basename($filePath) . '"');
     
    // Envoyer l'en-tête X-Sendfile à Apache
    header('X-Sendfile: ' . $filePath);
     
    // PHP peut s'arrêter ici, Apache prendra le relais
    exit();

    Conclusion
    Pour rediriger vers une page web virtuelle temporaire qui pointe vers un fichier demandé sans utiliser system() en PHP, mod_rewrite est la solution Apache native la plus élégante si le fichier est directement accessible par Apache. Si la logique de détermination du fichier est complexe et nécessite PHP, l'utilisation de fonctions PHP comme readfile() ou l'en-tête X-Sendfile (avec mod_xsendfile) sont des méthodes sûres et performantes.

    Évitez system() en PHP pour servir des fichiers car :
    • C'est un risque de sécurité majeur si les entrées utilisateur ne sont pas parfaitement nettoyées.
    • C'est moins performant que les méthodes natives du serveur web.
    • C'est moins portable entre les environnements.

Discussions similaires

  1. Réponses: 5
    Dernier message: 29/10/2010, 23h14
  2. Utiliser des commandes linux dans un shell
    Par Info_76 dans le forum Shell et commandes GNU
    Réponses: 4
    Dernier message: 20/03/2008, 12h03
  3. Réponses: 9
    Dernier message: 18/02/2008, 11h25
  4. utilisation des commandes shell dans un programme C
    Par rasgueados dans le forum Linux
    Réponses: 15
    Dernier message: 03/08/2006, 17h25
  5. Réponses: 2
    Dernier message: 21/02/2006, 10h36

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo