Re-enable chunking option for file delivery
Closed this issue · 4 comments
I think secure_downloads makes a serious effort on extending the functionality of typo3 when it comes to protecting downloads. As it already hooks into the generation of Urls and the file delivery, a seconday use case was to provide alternative methods for file delivery. AFAIK, typo3 does not natively support a chunked file delivery. This causes problems if you have large files in a non-public storage: At once point the PHP process will hit its memory limit.
Previous versions of secure_downloads (up to 4.1.0) have supported a chunked file delivery that reduced the memory requirement significantly to enable the (protected) download of large files. However, for some reason it was removed in 4.1.1.
I therefore suggest to re-enable this option. If there are some mechanisms in typo3 core already that I don't know of, some guidelines for how to deal with large files would be helpful.
Hi,
I also run in this issue. The following hack makes it working again (tested with version 4.1.1):
Under /Classes/Resource/FileDelivery.php replace the deliver()-function with the following:
/**
* Output the requested file
*/
public function deliver()
{
$file = GeneralUtility::getFileAbsFileName(ltrim($this->file, '/'));
$fileName = basename($file);
// This is a workaround for a PHP bug on Windows systems:
// @see http://bugs.php.net/bug.php?id=46990
// It helps for filenames with special characters that are present in latin1 encoding.
// If you have real UTF-8 filenames, use a nix based OS.
if (Environment::isWindows()) {
$file = utf8_decode($file);
}
$this->dispatchAfterFileRetrievedEvent($file, $fileName);
if (file_exists($file)) {
$this->fileSize = filesize($file);
$fileExtension = pathinfo($file, PATHINFO_EXTENSION);
$forceDownload = $this->shouldForceDownload($fileExtension);
$mimeType = MimeTypeUtility::getMimeType($file) ?? 'application/octet-stream';
// Hook for output:
// TODO: This hook is deprecated and will be removed with version 5. Use 'preReadFile' hook instead.
// TODO: Remove the pObj property with version 5.
$params = ['pObj' => &$this, 'fileExtension' => '.' . $fileExtension, 'mimeType' => &$mimeType];
HookUtility::executeHook('output', 'output', $params, $this);
$header = $this->getHeader($mimeType, $fileName, $forceDownload);
$outputFunction = $this->extensionConfiguration->getOutputFunction();
$this->dispatchBeforeFileDeliverEvent($outputFunction, $header, $fileName, $mimeType, $forceDownload);
if ($this->isProcessed === false && $this->extensionConfiguration->isLog()) {
$this->logDownload($this->fileSize, $mimeType);
}
foreach($header as $key => $value) {
header($key . ': ' . $value);
}
if ($this->shouldStreamFile($outputFunction)) {
$this->streamFile($file);
} else {
readfile ($file);
}
// make sure we can detect an aborted connection, call flush
ob_flush();
flush();
} else {
print 'File does not exist!';
}
Does this problem still exist? Then I would need more information to reproduce it.
Can the problem be solved if "delivery.outputFunction" is set to "fpassthru"? With the #102 error, I then had no problems with large videos.
It works on Version v5.0.0-rc1 in my case. So imho this can get closed.