mirror of
https://github.com/filegator/filegator.git
synced 2025-06-04 16:24:49 +02:00
120 lines
4.0 KiB
PHP
120 lines
4.0 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the FileGator package.
|
|
*
|
|
* (c) Milos Stojanovic <alcalbg@gmail.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE file
|
|
*/
|
|
|
|
namespace Filegator\Controllers;
|
|
|
|
use Filegator\Config\Config;
|
|
use Filegator\Kernel\Request;
|
|
use Filegator\Kernel\Response;
|
|
use Filegator\Services\Auth\AuthInterface;
|
|
use Filegator\Services\Storage\Filesystem;
|
|
use Filegator\Services\Tmpfs\TmpfsInterface;
|
|
|
|
class UploadController
|
|
{
|
|
protected $auth;
|
|
|
|
protected $config;
|
|
|
|
protected $storage;
|
|
|
|
protected $tmpfs;
|
|
|
|
public function __construct(Config $config, AuthInterface $auth, Filesystem $storage, TmpfsInterface $tmpfs)
|
|
{
|
|
$this->config = $config;
|
|
$this->auth = $auth;
|
|
$this->tmpfs = $tmpfs;
|
|
|
|
$user = $this->auth->user() ?: $this->auth->getGuest();
|
|
|
|
$this->storage = $storage;
|
|
$this->storage->setPathPrefix($user->getHomeDir());
|
|
}
|
|
|
|
public function chunkCheck(Request $request, Response $response)
|
|
{
|
|
$file_name = $request->input('resumableFilename', 'file');
|
|
$identifier = preg_replace('/[^0-9a-zA-Z_]/', '', $request->input('resumableIdentifier'));
|
|
$chunk_number = (int) $request->input('resumableChunkNumber');
|
|
|
|
$chunk_file = 'multipart_'.$identifier.$file_name.'.part'.$chunk_number;
|
|
|
|
if ($this->tmpfs->exists($chunk_file)) {
|
|
return $response->json('Chunk exists', 200);
|
|
}
|
|
|
|
return $response->json('Chunk does not exists', 204);
|
|
}
|
|
|
|
public function upload(Request $request, Response $response)
|
|
{
|
|
$file_name = $request->input('resumableFilename', 'file');
|
|
$destination = $request->input('resumableRelativePath');
|
|
$chunk_number = (int) $request->input('resumableChunkNumber');
|
|
$total_chunks = (int) $request->input('resumableTotalChunks');
|
|
$total_size = (int) $request->input('resumableTotalSize');
|
|
$identifier = preg_replace('/[^0-9a-zA-Z_]/', '', $request->input('resumableIdentifier'));
|
|
|
|
$file = $request->files->get('file');
|
|
|
|
if (! $file || ! $file->isValid() || $file->getSize() > $this->config->get('frontend_config.upload_max_size')) {
|
|
return $response->json('Bad file', 422);
|
|
}
|
|
|
|
$prefix = 'multipart_'.$identifier;
|
|
|
|
if ($this->tmpfs->exists($prefix.'_error')) {
|
|
return $response->json('Chunk too big', 422);
|
|
}
|
|
|
|
$stream = fopen($file->getPathName(), 'r');
|
|
|
|
$this->tmpfs->write($prefix.$file_name.'.part'.$chunk_number, $stream);
|
|
|
|
// check if all the parts present, and create the final destination file
|
|
$chunks_size = 0;
|
|
foreach ($this->tmpfs->findAll($prefix.'*') as $chunk) {
|
|
$chunks_size += $chunk['size'];
|
|
}
|
|
|
|
// file too big, cleanup to protect server, set error trap
|
|
if ($chunks_size > $this->config->get('frontend_config.upload_max_size')) {
|
|
foreach ($this->tmpfs->findAll($prefix.'*') as $tmp_chunk) {
|
|
$this->tmpfs->remove($tmp_chunk['name']);
|
|
}
|
|
$this->tmpfs->write($prefix.'_error', '');
|
|
|
|
return $response->json('Chunk too big', 422);
|
|
}
|
|
|
|
// if all the chunks are present, create final file and store it
|
|
if ($chunks_size >= $total_size) {
|
|
for ($i = 1; $i <= $total_chunks; ++$i) {
|
|
$part = $this->tmpfs->readStream($prefix.$file_name.'.part'.$i);
|
|
$this->tmpfs->write($file_name, $part['stream']);
|
|
}
|
|
|
|
$final = $this->tmpfs->readStream($file_name);
|
|
$res = $this->storage->store($destination, $final['filename'], $final['stream']);
|
|
|
|
// cleanup
|
|
$this->tmpfs->remove($file_name);
|
|
foreach ($this->tmpfs->findAll($prefix.'*') as $expired_chunk) {
|
|
$this->tmpfs->remove($expired_chunk['name']);
|
|
}
|
|
|
|
return $res ? $response->json('Stored') : $response->json('Error storing file');
|
|
}
|
|
|
|
return $response->json('Uploaded');
|
|
}
|
|
}
|