download: do not exit (#597)

Signed-off-by: Varun Patil <radialapps@gmail.com>
pull/602/head
Varun Patil 2023-04-20 11:33:54 -07:00
parent 4239e05b3c
commit 3e6e8f9b14
2 changed files with 137 additions and 102 deletions

View File

@ -114,7 +114,7 @@ class DownloadController extends GenericApiController
}
// Download multiple files
$this->multiple($name, $fileIds); // exits
return $this->multiple($name, $fileIds);
});
}
@ -127,7 +127,7 @@ class DownloadController extends GenericApiController
*/
public function one(int $fileid, bool $resumable = true, int $numChunks = 0): Http\Response
{
return Util::guardEx(function () use ($fileid, $resumable, $numChunks) {
return Util::guardExDirect(function (Http\IOutput $out) use ($fileid, $resumable, $numChunks) {
$file = $this->fs->getUserFile($fileid);
// check if http_range is sent by browser
@ -175,17 +175,17 @@ class DownloadController extends GenericApiController
// Only send partial content header if downloading a piece of the file
if ($seekStart > 0 || $seekEnd < ($size - 1)) {
header('HTTP/1.1 206 Partial Content');
$out->setHeader('HTTP/1.1 206 Partial Content');
}
// Set headers
header('Accept-Ranges: bytes');
header("Content-Range: bytes {$seekStart}-{$seekEnd}/{$size}");
header('Content-Length: '.($seekEnd - $seekStart + 1));
header('Content-Type: '.$file->getMimeType());
$out->setHeader('Accept-Ranges: bytes');
$out->setHeader("Content-Range: bytes {$seekStart}-{$seekEnd}/{$size}");
$out->setHeader('Content-Length: '.($seekEnd - $seekStart + 1));
$out->setHeader('Content-Type: '.$file->getMimeType());
// Make sure the browser downloads the file
header('Content-Disposition: attachment; filename="'.$file->getName().'"');
$out->setHeader('Content-Disposition: attachment; filename="'.$file->getName().'"');
// Open file to send
$res = $file->fopen('rb');
@ -215,7 +215,7 @@ class DownloadController extends GenericApiController
$chunkRead += \strlen($buffer);
// Send buffer
echo $buffer;
$out->setOutput($buffer);
// Flush output if chunk is large enough
if ($chunkRead > 1024 * 512) {
@ -235,8 +235,6 @@ class DownloadController extends GenericApiController
// Close file
fclose($res);
exit;
});
}
@ -246,8 +244,9 @@ class DownloadController extends GenericApiController
* @param string $name Name of zip file
* @param int[] $fileIds
*/
private function multiple(string $name, array $fileIds)
private function multiple(string $name, array $fileIds): Http\Response
{
return Util::guardExDirect(function ($out) use ($name, $fileIds) {
// Disable time limit
$executionTime = (int) \OC::$server->get(IniGetWrapper::class)->getNumeric('max_execution_time');
@set_time_limit(0);
@ -350,7 +349,6 @@ class DownloadController extends GenericApiController
// Done
$streamer->finalize();
exit;
});
}
}

View File

@ -27,6 +27,43 @@ trait UtilController
}
}
/**
* Return a callback response with guarded exceptions.
*/
public static function guardExDirect(\Closure $closure): Http\Response
{
return new class($closure) extends Http\Response implements Http\ICallbackResponse {
private \Closure $_closure;
public function __construct(\Closure $closure)
{
$this->_closure = $closure;
}
public function callback(Http\IOutput $output)
{
try {
($this->_closure)($output);
} catch (\OCA\Memories\HttpResponseException $e) {
$res = $e->response;
$output->setHttpResponseCode($res->getStatus());
if ($res instanceof Http\DataResponse) {
$output->setHeader('Content-Type: application/json');
$output->setOutput(json_encode($res->getData()));
} else {
$output->setOutput($res->render());
}
} catch (\Exception $e) {
$output->setHttpResponseCode(Http::STATUS_INTERNAL_SERVER_ERROR);
$output->setHeader('Content-Type: application/json');
$output->setOutput(json_encode([
'message' => $e->getMessage(),
]));
}
}
};
}
/**
* Get the current user.
*