Files

168 lines
4.5 KiB
PHP
Raw Permalink Normal View History

2018-09-27 14:01:00 +02:00
<?php
2026-04-20 22:46:47 +02:00
namespace Grocy\Controllers\Api;
2018-09-27 14:01:00 +02:00
2020-08-31 20:40:31 +02:00
use Grocy\Services\FilesService;
2023-05-13 14:43:51 +02:00
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
2020-08-31 20:07:46 +02:00
use Slim\Exception\HttpNotFoundException;
use Slim\Psr7\Stream;
2018-09-27 14:01:00 +02:00
class FilesApiController extends BaseApiController
{
2023-05-13 14:43:51 +02:00
public function DeleteFile(Request $request, Response $response, array $args)
2018-09-27 14:01:00 +02:00
{
try
{
2026-04-20 22:46:47 +02:00
if (!in_array($args['group'], $this->GetOpenApispec()->components->schemas->FileGroups->enum))
2021-07-02 20:29:53 +02:00
{
throw new \Exception('Invalid file group');
}
2020-08-31 20:40:31 +02:00
if (IsValidFileName(base64_decode($args['fileName'])))
{
$fileName = base64_decode($args['fileName']);
}
else
{
throw new \Exception('Invalid filename');
}
2018-09-27 14:01:00 +02:00
2026-04-20 22:46:47 +02:00
FilesService::GetInstance()->DeleteFile($args['group'], $fileName);
2018-09-30 22:16:33 +02:00
return $this->EmptyApiResponse($response);
2018-09-30 22:16:33 +02:00
}
catch (\Exception $ex)
{
return $this->GenericErrorResponse($response, $ex->getMessage());
2018-09-30 22:16:33 +02:00
}
}
2023-05-13 14:43:51 +02:00
public function ServeFile(Request $request, Response $response, array $args)
2018-09-30 22:16:33 +02:00
{
try
{
2026-04-20 22:46:47 +02:00
if (!in_array($args['group'], $this->GetOpenApispec()->components->schemas->FileGroups->enum))
2021-07-02 20:29:53 +02:00
{
throw new \Exception('Invalid file group');
}
2018-09-30 22:16:33 +02:00
if (str_contains($args['fileName'], '_'))
{
$fileInfo = explode('_', $args['fileName']);
$fileName = $this->CheckFileName($fileInfo[0]);
$fileNameOutput = $this->CheckFileName($fileInfo[1]);
$filePath = $this->GetFilePath($args['group'], $fileName, $request->getQueryParams());
}
else
{
$fileName = $this->CheckFileName($args['fileName']);
$fileNameOutput = $fileName;
$filePath = $this->GetFilePath($args['group'], $fileName, $request->getQueryParams());
}
2018-09-30 22:16:33 +02:00
if (file_exists($filePath))
{
$response = $response->withHeader('Cache-Control', 'max-age=2592000');
2018-09-30 22:16:33 +02:00
$response = $response->withHeader('Content-Type', mime_content_type($filePath));
$response = $response->withHeader('Content-Disposition', 'inline; filename="' . $fileNameOutput . '"');
return $response->withBody(new Stream(fopen($filePath, 'rb')));
2018-09-30 22:16:33 +02:00
}
else
{
2020-08-31 20:07:46 +02:00
throw new HttpNotFoundException($request, 'File not found');
2018-09-30 22:16:33 +02:00
}
2018-09-27 14:01:00 +02:00
}
catch (\Exception $ex)
{
2020-08-31 20:07:46 +02:00
throw new HttpNotFoundException($request, $ex->getMessage(), $ex);
2018-09-27 14:01:00 +02:00
}
}
2023-05-13 14:43:51 +02:00
public function UploadFile(Request $request, Response $response, array $args)
{
try
{
2026-04-20 22:46:47 +02:00
if (!in_array($args['group'], $this->GetOpenApispec()->components->schemas->FileGroups->enum))
2021-07-02 20:29:53 +02:00
{
throw new \Exception('Invalid file group');
}
2026-04-20 22:46:47 +02:00
$fileName = $this->CheckFileName($args['fileName']);
2021-07-02 20:29:53 +02:00
2026-04-20 22:46:47 +02:00
$fileHandle = fopen(FilesService::GetInstance()->GetFilePath($args['group'], $fileName), 'xb');
if ($fileHandle === false)
2024-02-23 17:56:32 +01:00
{
throw new \Exception("Error while creating file $fileName");
}
// Save the file to disk in chunks of 1 MB
$requestBody = $request->getBody();
while ($data = $requestBody->read(1048576))
{
if (fwrite($fileHandle, $data) === false)
{
throw new \Exception("Error while writing file $fileName");
}
}
if (fclose($fileHandle) === false)
{
throw new \Exception("Error while closing file $fileName");
}
return $this->EmptyApiResponse($response);
}
catch (\Exception $ex)
{
return $this->GenericErrorResponse($response, $ex->getMessage());
}
2020-08-31 20:40:31 +02:00
}
2026-04-20 22:46:47 +02:00
protected function CheckFileName(string $fileName)
2020-08-31 20:40:31 +02:00
{
if (IsValidFileName(base64_decode($fileName)))
{
$fileName = base64_decode($fileName);
}
else
{
throw new \Exception('Invalid filename');
}
return $fileName;
}
2020-08-31 20:07:46 +02:00
2026-04-20 22:46:47 +02:00
protected function GetFilePath(string $group, string $fileName, array $queryParams = [])
2020-08-31 20:07:46 +02:00
{
$forceServeAs = null;
2020-08-31 20:40:31 +02:00
if (isset($queryParams['force_serve_as']) && !empty($queryParams['force_serve_as']))
{
2020-08-31 20:07:46 +02:00
$forceServeAs = $queryParams['force_serve_as'];
}
2020-08-31 20:40:31 +02:00
if ($forceServeAs == FilesService::FILE_SERVE_TYPE_PICTURE)
{
2020-08-31 20:07:46 +02:00
$bestFitHeight = null;
2020-08-31 20:40:31 +02:00
if (isset($queryParams['best_fit_height']) && !empty($queryParams['best_fit_height']) && is_numeric($queryParams['best_fit_height']))
{
2020-08-31 20:07:46 +02:00
$bestFitHeight = $queryParams['best_fit_height'];
}
$bestFitWidth = null;
2020-08-31 20:40:31 +02:00
if (isset($queryParams['best_fit_width']) && !empty($queryParams['best_fit_width']) && is_numeric($queryParams['best_fit_width']))
{
2020-08-31 20:07:46 +02:00
$bestFitWidth = $queryParams['best_fit_width'];
}
2026-04-20 22:46:47 +02:00
$filePath = FilesService::GetInstance()->DownscaleImage($group, $fileName, $bestFitHeight, $bestFitWidth);
2020-08-31 20:40:31 +02:00
}
else
{
2026-04-20 22:46:47 +02:00
$filePath = FilesService::GetInstance()->GetFilePath($group, $fileName);
2020-08-31 20:07:46 +02:00
}
2020-08-31 20:40:31 +02:00
2020-08-31 20:07:46 +02:00
return $filePath;
}
2018-09-27 14:01:00 +02:00
}