How to download a (large) file with a typo3 extbase controller action

Viewed 74

I have a controller with a download action in typo3. For some time I have implemented it like this and it is working:

function downloadAction() {
  // ...
  // send headers ...
  // ...
  if ($fh = fopen($this->file, 'r')) {
    while (!feof($fh)) {
      echo fread($fh, $chunkSize); // send file in little chunks to output buffer
      flush();
    }
    fclose($fh);
  }
  exit; // Stopp middlewares and so on.
}

I am wondering if I should/could return an object of type ResponseInterface in typo3 11. So it is obviously that exit stopps the middleware pipeline and other things and I don't really know if there are any side effects.

I tried the following to return a ResponseInterface :

function downloadAction(): ResponseInterface {
  // ...
  return $this->responseFactory->createResponse();
    ->withAddedHeader(...)
    // ...
    ->withBody($this->streamFactory->createStreamFromFile($this->file))
    ->withStatus(200, 'OK');
}

The problem is that the solution with the ResponseInterface works only with small files. The problem seems to be in Bootstrap::handleFrontendRequest().

protected function handleFrontendRequest(ServerRequestInterface $request): string
{
  // ...
  if (headers_sent() === false) {
    // send headers      
  }
  $body = $response->getBody(); // get the stream
  $body->rewind();
  $content = $body->getContents(); // Problem: Read the hole stream into RAM instead of
                                   // sending it in chunks to the output buffer
  // ...
  return $content;
}

typo3 tries to read the whole stream/file into RAM. That crashes the application.

So how should I trigger a file download these days with typo3?

0 Answers
Related