feat(storage): implement S3 file upload and temporary URL generation functionality
This commit is contained in:
39
app/Domains/StorageTest/Controllers/S3TestController.php
Normal file
39
app/Domains/StorageTest/Controllers/S3TestController.php
Normal file
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\StorageTest\Controllers;
|
||||
|
||||
use App\Domains\StorageTest\Requests\GenerateS3TemporaryUrlRequest;
|
||||
use App\Domains\StorageTest\Requests\StoreS3TestFileRequest;
|
||||
use App\Domains\StorageTest\Services\S3TestService;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
class S3TestController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
protected S3TestService $s3TestService,
|
||||
) {
|
||||
}
|
||||
|
||||
public function store(StoreS3TestFileRequest $request): JsonResponse
|
||||
{
|
||||
return response()->json(
|
||||
$this->s3TestService->storeTestFile(
|
||||
$request->file('file'),
|
||||
$request->validated('directory'),
|
||||
(int) $request->validated('expires_in_minutes', 10),
|
||||
),
|
||||
201,
|
||||
);
|
||||
}
|
||||
|
||||
public function temporaryUrl(GenerateS3TemporaryUrlRequest $request): JsonResponse
|
||||
{
|
||||
return response()->json(
|
||||
$this->s3TestService->generateTemporaryUrl(
|
||||
$request->validated('path'),
|
||||
(int) $request->validated('expires_in_minutes', 10),
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\StorageTest\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class GenerateS3TemporaryUrlRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int, string>>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'path' => ['required', 'string', 'max:2048'],
|
||||
'expires_in_minutes' => ['nullable', 'integer', 'min:1', 'max:1440'],
|
||||
];
|
||||
}
|
||||
}
|
||||
25
app/Domains/StorageTest/Requests/StoreS3TestFileRequest.php
Normal file
25
app/Domains/StorageTest/Requests/StoreS3TestFileRequest.php
Normal file
@@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\StorageTest\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class StoreS3TestFileRequest extends FormRequest
|
||||
{
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, array<int, string>>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'file' => ['required', 'file', 'max:10240'],
|
||||
'directory' => ['nullable', 'string', 'max:255'],
|
||||
'expires_in_minutes' => ['nullable', 'integer', 'min:1', 'max:1440'],
|
||||
];
|
||||
}
|
||||
}
|
||||
79
app/Domains/StorageTest/Services/S3TestService.php
Normal file
79
app/Domains/StorageTest/Services/S3TestService.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Domains\StorageTest\Services;
|
||||
|
||||
use Illuminate\Http\UploadedFile;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class S3TestService
|
||||
{
|
||||
/**
|
||||
* @return array<string, int|string|null>
|
||||
*/
|
||||
public function storeTestFile(
|
||||
UploadedFile $file,
|
||||
?string $directory = null,
|
||||
int $expiresInMinutes = 10,
|
||||
): array {
|
||||
$directory = $this->normalizeDirectory($directory);
|
||||
$disk = Storage::disk('s3');
|
||||
$path = $disk->putFile($directory, $file);
|
||||
|
||||
if (! is_string($path) || $path === '') {
|
||||
Log::error('S3 upload returned an empty path.', [
|
||||
'disk' => 's3',
|
||||
'directory' => $directory,
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'mime_type' => $file->getClientMimeType(),
|
||||
'size' => $file->getSize(),
|
||||
]);
|
||||
|
||||
throw new RuntimeException('No se pudo subir el archivo al disco s3.');
|
||||
}
|
||||
|
||||
return [
|
||||
'disk' => 's3',
|
||||
'directory' => $directory,
|
||||
'path' => $path,
|
||||
'filename' => basename($path),
|
||||
'original_name' => $file->getClientOriginalName(),
|
||||
'mime_type' => $file->getClientMimeType(),
|
||||
'extension' => $file->extension(),
|
||||
'size' => $file->getSize(),
|
||||
'temporary_url' => $disk->temporaryUrl($path, now()->addMinutes($expiresInMinutes)),
|
||||
'temporary_url_expires_at' => now()->addMinutes($expiresInMinutes)->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
*/
|
||||
public function generateTemporaryUrl(string $path, int $expiresInMinutes = 10): array
|
||||
{
|
||||
return [
|
||||
'disk' => 's3',
|
||||
'path' => $path,
|
||||
'temporary_url' => $this->temporaryUrlForPath($path, $expiresInMinutes),
|
||||
'temporary_url_expires_at' => now()->addMinutes($expiresInMinutes)->toIso8601String(),
|
||||
];
|
||||
}
|
||||
|
||||
protected function temporaryUrlForPath(string $path, int $expiresInMinutes): string
|
||||
{
|
||||
return Storage::disk('s3')->temporaryUrl($path, now()->addMinutes($expiresInMinutes));
|
||||
}
|
||||
|
||||
protected function normalizeDirectory(?string $directory): string
|
||||
{
|
||||
$directory = trim((string) $directory, '/');
|
||||
|
||||
if ($directory !== '') {
|
||||
return $directory;
|
||||
}
|
||||
|
||||
return 'testing/attachments/'.now()->format('Y/m/d').'/'.Str::uuid();
|
||||
}
|
||||
}
|
||||
9
app/Domains/StorageTest/routes/api.php
Normal file
9
app/Domains/StorageTest/routes/api.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
use App\Domains\StorageTest\Controllers\S3TestController;
|
||||
use Illuminate\Support\Facades\Route;
|
||||
|
||||
Route::prefix('storage-test/s3')->group(function (): void {
|
||||
Route::post('upload', [S3TestController::class, 'store']);
|
||||
Route::get('temporary-url', [S3TestController::class, 'temporaryUrl']);
|
||||
});
|
||||
Reference in New Issue
Block a user