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
stops 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?