Manage uploaded files
This commit is contained in:
77
api/common/Controller/Files.php
Normal file
77
api/common/Controller/Files.php
Normal file
@ -0,0 +1,77 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Controller;
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface as Request;
|
||||
use Psr\Http\Message\ResponseInterface as Response;
|
||||
use ProVM\Common\Define\Controller\Json;
|
||||
use Contabilidad\Common\Service\FileHandler as Handler;
|
||||
use ProVM\Common\Factory\Model as Factory;
|
||||
use Contabilidad\Cuenta;
|
||||
|
||||
class Files {
|
||||
use Json;
|
||||
|
||||
public function __invoke(Request $request, Response $response, Handler $handler): Response {
|
||||
$files = $handler->listFiles();
|
||||
usort($files, function($a, $b) {
|
||||
$f = strcmp($a->folder, $b->folder);
|
||||
if ($f == 0) {
|
||||
return strcmp($a->filename, $b->filename);
|
||||
}
|
||||
return $f;
|
||||
});
|
||||
return $this->withJson($response, compact('files'));
|
||||
}
|
||||
public function upload(Request $request, Response $response, Handler $handler, Factory $factory): Response {
|
||||
$post = $request->getParsedBody();
|
||||
$cuenta = $factory->find(Cuenta::class)->one($post['cuenta']);
|
||||
$file = $request->getUploadedFiles()['archivo'];
|
||||
$new_name = implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post['fecha']]);
|
||||
$output = [
|
||||
'input' => [
|
||||
'name' => $file->getClientFilename(),
|
||||
'type' => $file->getClientMediaType(),
|
||||
'size' => $file->getSize(),
|
||||
'error' => $file->getError()
|
||||
],
|
||||
'new_name' => $new_name,
|
||||
'uploaded' => $handler->uploadFile($file, $new_name)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function get(Request $request, Response $response, Handler $handler, $folder, $filename): Response {
|
||||
$file = $handler->getFile($folder, $filename);
|
||||
return $response
|
||||
->withHeader('Content-Type', $handler->getType($folder))
|
||||
->withHeader('Content-Disposition', 'attachment; filename=' . $filename)
|
||||
->withAddedHeader('Cache-Control', 'no-store, no-cache, must-revalidate, max-age=0')
|
||||
->withHeader('Cache-Control', 'post-check=0, pre-check=0')
|
||||
->withHeader('Pragma', 'no-cache')
|
||||
->withBody($file);
|
||||
}
|
||||
public function edit(Request $request, Response $response, Handler $handler, Factory $factory, $folder, $filename): Response {
|
||||
$post = json_decode($request->getBody());
|
||||
$cuenta = $factory->find(Cuenta::class)->one($post->cuenta);
|
||||
$filenfo = $handler->getInfo($folder, $filename);
|
||||
$new_name = implode('.', [implode(' - ', [$cuenta->nombre, $cuenta->categoria()->nombre, $post->fecha]), $filenfo->getExtension()]);
|
||||
$output = [
|
||||
'input' => [
|
||||
'folder' => $folder,
|
||||
'filename' => $filename,
|
||||
'post' => $post
|
||||
],
|
||||
'edited' => $handler->editFilename($folder, $filename, $new_name)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
public function delete(Request $request, Response $response, Handler $handler, $folder, $filename): Response {
|
||||
$output = [
|
||||
'input' => [
|
||||
'folder' => $folder,
|
||||
'filename' => $filename
|
||||
],
|
||||
'deleted' => $handler->deleteFile($folder, $filename)
|
||||
];
|
||||
return $this->withJson($response, $output);
|
||||
}
|
||||
}
|
109
api/common/Service/FileHandler.php
Normal file
109
api/common/Service/FileHandler.php
Normal file
@ -0,0 +1,109 @@
|
||||
<?php
|
||||
namespace Contabilidad\Common\Service;
|
||||
|
||||
use Psr\Http\Message\UploadedFileInterface;
|
||||
use Psr\Http\Message\StreamInterface;
|
||||
use Nyholm\Psr7\Stream;
|
||||
|
||||
class FileHandler {
|
||||
protected $base_folder;
|
||||
protected $valid_types;
|
||||
protected $folders;
|
||||
public function __construct(object $params) {
|
||||
$this->base_folder = $params->folder;
|
||||
$this->addValidTypes(array_keys($params->types));
|
||||
$this->addFolders($params->types);
|
||||
}
|
||||
public function addFolders(array $folders): FileHandler {
|
||||
foreach ($folders as $type => $folder) {
|
||||
$this->addFolder($type, $folder);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addFolder(string $type, string $folder): FileHandler {
|
||||
$this->folders[$type] = $folder;
|
||||
return $this;
|
||||
}
|
||||
public function addValidTypes(array $valid_types): FileHandler {
|
||||
foreach ($valid_types as $type) {
|
||||
$this->addValidType($type);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
public function addValidType(string $type): FileHandler {
|
||||
$this->valid_types []= $type;
|
||||
return $this;
|
||||
}
|
||||
public function getType(string $folder): string {
|
||||
return array_search($folder, $this->folders);
|
||||
}
|
||||
|
||||
public function uploadFile(UploadedFileInterface $file, string $new_name = null): bool {
|
||||
if ($file->getError() !== UPLOAD_ERR_OK) {
|
||||
return false;
|
||||
}
|
||||
if (!in_array($file->getClientMediaType(), array_keys($this->valid_types))) {
|
||||
return false;
|
||||
}
|
||||
if ($new_name === null) {
|
||||
$new_name = $file->getClientFilename();
|
||||
}
|
||||
$filenfo = new \SplFileInfo($file->getClientFilename());
|
||||
if (!str_contains($new_name, $filenfo->getExtension())) {
|
||||
$new_name .= '.' . $filenfo->getExtension();
|
||||
}
|
||||
$to = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $this->folders[$file->getClientMediaType()], $new_name]);
|
||||
$file->moveTo($to);
|
||||
return file_exists($to);
|
||||
}
|
||||
public function listFiles(): array {
|
||||
$output = [];
|
||||
foreach ($this->folders as $f) {
|
||||
$folder = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $f]);
|
||||
$files = new \DirectoryIterator($folder);
|
||||
foreach ($files as $file) {
|
||||
if ($file->isDir()) {
|
||||
continue;
|
||||
}
|
||||
$output []= (object) ['folder' => $f, 'filename' => $file->getBasename()];
|
||||
}
|
||||
}
|
||||
return $output;
|
||||
}
|
||||
protected function validateFilename(string $folder, string $filename): bool|string {
|
||||
if (!in_array($folder, $this->folders)) {
|
||||
return false;
|
||||
}
|
||||
$f = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $folder, $filename]);
|
||||
if (!file_exists($f)) {
|
||||
return false;
|
||||
}
|
||||
return $f;
|
||||
}
|
||||
public function getInfo(string $folder, string $filename): \SplFileInfo|bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return new \SplFileInfo($f);
|
||||
}
|
||||
public function getFile(string $folder, string $filename): StreamInterface|bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return Stream::create(file_get_contents($f));
|
||||
}
|
||||
public function editFilename(string $folder, string $filename, string $new_name): bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
$info = new \SplFileInfo($f);
|
||||
$new = implode(DIRECTORY_SEPARATOR, [$this->base_folder, $folder, $new_name . '.' . $info->getExtension()]);
|
||||
return rename($f, $new);
|
||||
}
|
||||
public function deleteFile(string $folder, string $filename): bool {
|
||||
if (!$f = $this->validateFilename($folder, $filename)) {
|
||||
return false;
|
||||
}
|
||||
return unlink($f);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user