mirror of
https://github.com/VueFileManager/vuefilemanager.git
synced 2026-04-18 00:02:15 +00:00
remote upload backend functionality
This commit is contained in:
102
src/Domain/Files/Actions/GetContentFromExternalSource.php
Normal file
102
src/Domain/Files/Actions/GetContentFromExternalSource.php
Normal file
@@ -0,0 +1,102 @@
|
||||
<?php
|
||||
namespace Domain\Files\Actions;
|
||||
|
||||
use App\Users\Models\User;
|
||||
use Domain\Files\Models\File;
|
||||
use Error;
|
||||
use ErrorException;
|
||||
use Illuminate\Support\Str;
|
||||
use Domain\Sharing\Models\Share;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Log;
|
||||
use Spatie\QueueableAction\QueueableAction;
|
||||
|
||||
class GetContentFromExternalSource
|
||||
{
|
||||
use QueueableAction;
|
||||
|
||||
public function __construct(
|
||||
public ProcessFileAction $processFile,
|
||||
public StoreFileExifMetadataAction $storeExifMetadata,
|
||||
public MoveFileToFTPStorageAction $moveFileToFTPStorage,
|
||||
public ProcessImageThumbnailAction $createImageThumbnail,
|
||||
public MoveFileToExternalStorageAction $moveFileToExternalStorage,
|
||||
) {}
|
||||
|
||||
public function __invoke(
|
||||
array $payload,
|
||||
User $user,
|
||||
) {
|
||||
foreach ($payload['urls'] as $url) {
|
||||
try {
|
||||
// Get local disk instance
|
||||
$localDisk = Storage::disk('local');
|
||||
|
||||
// Get file from external source
|
||||
$response = Http::get($url);
|
||||
|
||||
// Get extension from response
|
||||
$extension = extractExtensionFromUrl($url, $response);
|
||||
|
||||
// Get blacklisted mimetypes
|
||||
$this->checkDisabledMimetypes($extension);
|
||||
|
||||
// Get file basename
|
||||
$basename = Str::uuid() . ".$extension";
|
||||
|
||||
// Get file name
|
||||
$name = array_key_exists('filename', pathinfo($url))
|
||||
? explode('?', pathinfo($url)['filename'])[0]
|
||||
: Str::uuid();
|
||||
|
||||
// Get file path
|
||||
$path = "files/$user->id/$basename";
|
||||
|
||||
// Store file to main storage disk
|
||||
$localDisk->put($path, $response->getBody());
|
||||
|
||||
// Create multiple image thumbnails
|
||||
($this->createImageThumbnail)($basename, $user->id);
|
||||
|
||||
// Create new file
|
||||
$file = File::create([
|
||||
'mimetype' => $extension,
|
||||
'type' => getFileType($localDisk->mimeType($path)),
|
||||
'parent_id' => $payload['parent_id'] ?? null,
|
||||
'name' => $name ?? $basename,
|
||||
'basename' => $basename,
|
||||
'filesize' => $localDisk->size($path),
|
||||
'user_id' => $user->id,
|
||||
'creator_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
// Store file exif information
|
||||
($this->storeExifMetadata)($file);
|
||||
|
||||
// Move file to external storage
|
||||
match (config('filesystems.default')) {
|
||||
's3' => ($this->moveFileToExternalStorage)($basename, $user->id),
|
||||
'ftp', 'azure' => ($this->moveFileToFTPStorage)($basename, $user->id),
|
||||
default => null
|
||||
};
|
||||
} catch ( ErrorException | Error $e) {
|
||||
Log::error("Remote upload failed as {$e->getMessage()}");
|
||||
Log::error($e->getTraceAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $extension
|
||||
*/
|
||||
protected function checkDisabledMimetypes(?string $extension): void
|
||||
{
|
||||
$mimetypeBlacklist = explode(',', get_settings('mimetypes_blacklist')) ?? null;
|
||||
|
||||
// If is extension in mimetype blacklist, Abort!
|
||||
if ($extension && array_intersect([str_replace('.', '', ".$extension")], $mimetypeBlacklist)) {
|
||||
abort(422);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/Domain/Files/Controllers/RemoteUploadFileController.php
Normal file
36
src/Domain/Files/Controllers/RemoteUploadFileController.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Domain\Files\Controllers;
|
||||
|
||||
use Domain\Folders\Models\Folder;
|
||||
use Illuminate\Http\Response;
|
||||
use Domain\Sharing\Models\Share;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Domain\Files\Requests\RemoteUploadRequest;
|
||||
use Domain\Files\Actions\GetContentFromExternalSource;
|
||||
|
||||
class RemoteUploadFileController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
public GetContentFromExternalSource $getContentFromExternalSource,
|
||||
) {}
|
||||
|
||||
public function __invoke(RemoteUploadRequest $request, ?Share $shared = null): Response|array
|
||||
{
|
||||
if (is_demo_account()) {
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
|
||||
// Get user
|
||||
$user = $request->filled('parent_id')
|
||||
? Folder::find($request->input('parent_id'))->getLatestParent()->user
|
||||
: auth()->user();
|
||||
|
||||
// Execute job for get content from url and save
|
||||
($this->getContentFromExternalSource)
|
||||
->onQueue()
|
||||
->execute($request->all(), $user);
|
||||
|
||||
return response('Files were successfully added to the upload queue', 201);
|
||||
}
|
||||
}
|
||||
30
src/Domain/Files/Requests/RemoteUploadRequest.php
Normal file
30
src/Domain/Files/Requests/RemoteUploadRequest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
namespace Domain\Files\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class RemoteUploadRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'urls.*' => 'required|url',
|
||||
'parent_id' => 'nullable|uuid',
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1157,4 +1157,36 @@ if (! function_exists('replace_occurrence')) {
|
||||
return "{$degrees}°$minutes'$seconds\"$ref";
|
||||
}
|
||||
}
|
||||
|
||||
if (! function_exists('extractExtensionFromUrl')) {
|
||||
/**
|
||||
* Extract extension from the url
|
||||
*
|
||||
* TODO: make unit test
|
||||
*/
|
||||
function extractExtensionFromUrl($url, $response): string|null
|
||||
{
|
||||
$string = str_replace(['&'], '?', pathinfo($url)['extension']);
|
||||
|
||||
// Get extension from url path
|
||||
$extension = array_key_exists('extension', pathinfo($url))
|
||||
? explode('?', $string)[0]
|
||||
: null;
|
||||
|
||||
// Return pure extension
|
||||
if ($extension) {
|
||||
return $extension;
|
||||
}
|
||||
|
||||
// Prepare header for extracting content-type line
|
||||
$header = array_change_key_case($response->headers(), CASE_LOWER);
|
||||
|
||||
// Get extension
|
||||
if (array_key_exists('content-type', $header)) {
|
||||
return '.' . explode('/', $header['content-type'][0])[1];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user