Section: Renvoyer un fichier binaire
« Générer un PDF avec TCPDF | ^ Générer du contenu avec les vues | Générer un fichier zip » |
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.
Pour renvoyer un fichier existant :
$rep->fileName = jApp::varPath('fichier_a_renvoyer.gif');
Et sinon, si vous générez vous-même, mettez le contenu dans une chaîne et mettez
le dans content
:
$rep->content = '...';
Cependant, cela prendra autant de mémoire que la taille du contenu, 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.
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;
`