Raccourcis : Contenu - rubriques - sous rubriques
EN FR

Pour renvoyer un fichier binaire (un exécutable, une image, une vidéo, une archive ou autre), il faut utiliser jResponseBinary dont l'alias est "binary"


$rep = $this->getResponse('binary');

En premier lieu, il vous faut indiquer dans la propriété $outputFileName le nom de fichier sous lequel apparaîtra le contenu à l'utilisateur.


 $rep->outputFileName = 'monfichier.gif';

Vous pouvez aussi définir le type mime du contenu :


 $rep->mimeType = 'image/gif';

Et vous devez aussi spécifier si le fichier doit être proposé à l'utilisateur pour l'enregistrement ou non. Pour des fichiers couramment pris en charge par les navigateurs (les images par exemple), on mettra false :


 $rep->doDownload = false;

Ensuite pour le contenu, vous pouvez indiquer soit un fichier existant, soit du contenu que vous générez vous-même.

Renvoyer un fichier

Pour renvoyer un fichier existant, indiquer le chemin du fichier dans la propriété fileName :


 $rep->fileName = jApp::varPath('fichier_a_renvoyer.gif');

Le contenu du fichier est envoyé directement au navigateur une fois le traitement du contrôleur terminé.

Plutôt qu'instancier soit-même une réponse "binary" et de manipuler ses propriétés, il est possible d'utiliser la méthode getFileResponse(). Cette méthode accepte le chemin du fichier à renvoyer, et un boolean indiquant si il faut activer le cache HTTP ou non.

Dans cette exemple, cela renvoi un pdf directement.


class myController extends jController
{

  public function getInvoice()
  {
      $invoiceFile = '/somewhere/invoices/invoice202505.pdf';

      return $this->getFileResponse($invoiceFile);
  }
}

À noter que :

  • Le type mime est automatiquement déclaré, en fonction de l'extension du nom du

fichier.

  • Le nom du fichier présenté à l'utilisateur est celui du fichier original
  • Pas de téléchargement forcé (doDownload à false).
  • Si le fichier n'est pas trouvé, une erreur 404 est renvoyée.
  • Si le cache HTTP est activé, sa validité est conditionnée par la date de modification du fichier.

Si vous voulez changer ces conditions, récupérez l'objet renvoyé par getFileResponse, et manipulez-le comme indiqué plus haut avant de le renvoyé.


class myController extends jController
{

  public function getInvoice()
  {
      $invoiceFile = '/somewhere/invoices/invoice202505.pdf';

      $response = $this->getFileResponse($invoiceFile);
      $response->doDownload = true;
      return $response;
  }
}

Renvoyer un contenu de petite taille

Si vous générez vous-même le contenu du fichier, mettez le contenu dans une chaîne et mettez le dans content. Exemple :


 $rep->content = $myComponent->generateContent();

Cependant, il ne faut utiliser cette manière de faire que pour les petits contenus (en dessous de 1Mo par exemple). En effet, ici le contenu occupera de la mémoire, ce qui peut être problématique si le contenu est volumineux (plusieurs megaoctets). PHP pourrait interrompre brusquement le script si il n'y a plus assez de mémoire ou si la taille mémoire maximale configurée dans PHP est atteinte.

Renvoyer un contenu volumineux

Pour les contenus volumineux, il est préférable d'envoyer directement le contenu au fur et à mesure qu'on le génère ou qu'on le lit à partir d'une source de données.

Pour cela, on peut donnée à jResponseBinary, soit une fonction de callback qui sera appelée au moment où Jelix demandera d'envoyer le contenu, soit un iterateur/générateur. Il faut utiliser respectivement les méthodes setContentCallback() et setContentGenerator().

Exemple, en donnant en réponse le contenu de la réponse à une requête HTTP, effectuée avec la bibliothèque GuzzleHttp :



// on prépare et envoie la requête à un service tiers
$client = new GuzzleHttp\Client();
$request = new GuzzleHttp\Psr7\Request('GET', 'https://foo.example/content', $headers);
$response = $client->send($request, ['stream' => true]);

// on récupère la réponse sous forme de flux, qui n'est pas encore consommé
$stream = $response->getBody();

$rep = $this->getResponse('binary');

// on donne une fonction de callback, qui lira le flux et l'enverra sur la sortie de PHP (`php://output`),
// grâce à cet utilitaire copyToStream
$rep->setContentCallback(function () use ($response) {
    $output = Psr7\Utils::streamFor(fopen('php://output', 'w+'));
    Psr7\Utils::copyToStream( $response->getBody(), $output);
});
// ..
return $rep;

Autre exemple avec un générateur

`

class Business {

    // this function is a generator, because of the use of yield
    public function getAllData()
    {
        $db = jDb::getConnection();
        $resultSet = $db->query("SELECT field1, field2, field3 FROM hugeTable")
        foreach($resultSet as $record) {
            yield $record->field1.';'.$record->field2.';'.$record->field3."\n";
        }
    }

}

// Into the controller:

$obj = new Business();

$rep = $this->getResponse('binary'); $rep->setContentGenerator($obj->getAllData()); // .. return $rep; `