Quick links: Content - sections - sub sections
EN FR

To send binary content to the user (a graphic, a video, some sound, an archive, etc.), jResponseBinary should be used. To use it, indicate 'binary' as the type of response.


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

Afterwards, some variables need to be set to a correct value before content is displayed.

First, you have to set outputFileName property. outputFileName will be the name shown to the user.


 $resp->outputFileName = 'filename.gif';

Next, you can define the mime type of your content:


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

You have an option for files you want the user to download (particularly, files not rendered by common browsers - archives, for example). To force the download of the file, simple set doDownload to true.


 $resp->doDownload = true;

For the content itself, you have to define either the filename or the content property.

Sending a file

To send an existing file, just use filename:


   $resp->fileName = jApp::varPath('file_to_send.gif');

The file content is sent directly to the browser once the controller has finished processing.

Rather than instantiating a “binary” response yourself and manipulating its properties, you can use the getFileResponse() method. This method accepts the path of the file to be returned and a boolean indicating whether to enable the HTTP cache or not.

In this example, it returns a PDF directly.


class myController extends jController
{

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

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

Please note:

  • The MIME type is automatically declared based on the filename extension
  • The filename displayed to the user is that of the original file
  • No forced download (doDownload set to false).
  • If the file is not found, a 404 error is returned.
  • If the HTTP cache is enabled, its validity is determined by the file modification date.

If you want to change these conditions, retrieve the object returned by getFileResponse, and manipulate it as indicated above before returning it.


class myController extends jController
{

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

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

Sending a lightweight content

If your content is generated or comes from your database for example, set it on the content property:


   $resp->content = '...';

However, it will take as much memory as the size of the content, so it could be an issue if the content is huge (higher than 1MB). PHP could stop the script if there is not enough memory or if the maximal memory amount configured into PHP is reached.

Sending huge content

For huge content, it is better to send it directly during the reading of the data source, when Jelix will be able to send it to the browser.

There are two methods on jResponseBinary. Use setContentCallback() to give a callback function that will fetch the content from somewhere and return it to the PHP output. Or use setContentGenerator() to give an iterator or a generator.

Here is an example, by sending to the browser the response of an HTTP request made with GuzzleHttp:



// we prepare and send the HTTP request to a specific service
$client = new GuzzleHttp\Client();
$request = new GuzzleHttp\Psr7\Request('GET', 'https://foo.example/content', $headers);
$response = $client->send($request, ['stream' => true]);

// we retrieve the http response as a stream, that is not consumed yet.
$stream = $response->getBody();

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

// we give a callback function that read the stream and send it to the PHP output (`php://output`),
// with copyToStream
$rep->setContentCallback(function () use ($response) {
    $output = Psr7\Utils::streamFor(fopen('php://output', 'w+'));
    Psr7\Utils::copyToStream( $response->getBody(), $output);
});
// ..
return $rep;

An other example with a generator



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;