andreinocenti / laravel-file-s3-like
A package to upload, update, delete, purge a S3 like storage via Laravel
Installs: 316
Dependents: 0
Suggesters: 0
Security: 0
Stars: 3
Watchers: 1
Forks: 0
Open Issues: 0
pkg:composer/andreinocenti/laravel-file-s3-like
Requires
- php: ^8.2
- google/cloud-storage: ^1.48
- illuminate/contracts: ^8.0|^9.0|^10.0|^11.0|^12.0
- illuminate/http: ^8.0|^9.0|^10.0|^11.0|^12.0
- illuminate/support: ^8.0|^9.0|^10.0|^11.0|^12.0
- league/flysystem-aws-s3-v3: ^1.0|^2.0|^3.0
- spatie/laravel-google-cloud-storage: ^2.3
- xantios/mimey: ^2.2
Requires (Dev)
- laravel/pint: ^1.15
- orchestra/testbench: ^9.9 || ^10.0
- pestphp/pest: ^2.34
- pestphp/pest-plugin-laravel: ^2.34
- phpstan/phpstan: ^1.11
- phpunit/phpunit: ^10.5
README
This is a Laravel package that handles and make easy the upload, overwrite, delete, cdn purge of files and directories on AWS S3 like cloud storages.
It supports sending a file URL, a form uploaded file (UploadedFile) or a base64 file string.
It supports generating a presigned url.
Support
Currently supports:
- Digital Ocean SPACES
- Google Cloud Storage (GCS)
In the future I will add new cloud storages support or accept pull requests.
Configuration
You should install it via composer:
composer require andreinocenti/laravel-file-s3-like
1. Digital Ocean Spaces
This package use the Laravel Illuminate\Support\Facades\Storage facade to handle the files.
So you must config the filesystem AWS like disk that you want to use.
Below the optimal config to be used in config/filesystem.php:
'spaces-disk' => [ 'driver' => 's3', 'key' => env('SPACES_ACCESS_KEY_ID'), 'secret' => env('SPACES_SECRET_ACCESS_KEY'), 'region' => env('SPACES_DEFAULT_REGION'), 'bucket' => env('SPACES_BUCKET'), 'url' => env('SPACES_URL'), 'endpoint' => env('SPACES_ENDPOINT'), 'folder' => env('SPACES_FOLDER'), // This will be the default directory used. It can be empty, if so the default directory will be the bucket root 'cdn_endpoint' => env('SPACES_CDN_ENDPOINT'), // at Digital Ocean Spaces the CDN is auto set when a file is uploaded. So set here the cdn_endpoint (edge) 'use_path_style_endpoint' => env('SPACES_USE_PATH_STYLE_ENDPOINT', false), 'throw' => false, ],
2. Google Cloud Storage (GCS)
To use GCS, you need to install the required dependencies:
composer require google/cloud-storage spatie/laravel-google-cloud-storage
Then configure the disk in config/filesystem.php:
'gcs' => [ 'driver' => 'gcs', 'project_id' => env('GOOGLE_CLOUD_PROJECT_ID', 'your-project-id'), 'key_file_path' => env('GOOGLE_APPLICATION_CREDENTIALS'), // Path to service account json file 'bucket' => env('GOOGLE_CLOUD_STORAGE_BUCKET', 'your-bucket'), 'path_prefix' => env('GOOGLE_CLOUD_STORAGE_PATH_PREFIX', null), // Optional: prefix for all files 'storage_api_uri' => env('GOOGLE_CLOUD_STORAGE_API_URI', null), // Optional: custom API URI 'api_endpoint' => env('GOOGLE_CLOUD_STORAGE_API_ENDPOINT', null), // Optional: custom API endpoint 'visibility' => 'public', // Default visibility 'throw' => false, ],
Ensure you have your Google Cloud Service Account JSON key file reachable and the path correctly set in GOOGLE_APPLICATION_CREDENTIALS environment variable.
Usage
Digital Ocean Spaces
You can use the FileS3LikeSpaces facade:
use AndreInocenti\LaravelFileS3Like\Facades\FileS3LikeSpaces; FileS3LikeSpaces::disk('spaces-disk') ->directory('images') ->upload($file, 'new-test');
Or using the generic FileS3Like facade:
use AndreInocenti\LaravelFileS3Like\Facades\FileS3Like; FileS3Like::repository('spaces') ->disk('spaces-disk') ->directory('images') ->upload($file, 'new-test');
Google Cloud Storage (GCS)
Use the FileS3Like facade with the gcs repository:
use AndreInocenti\LaravelFileS3Like\Facades\FileS3Like; FileS3Like::repository('gcs') ->disk('gcs') // The disk name configured in config/filesystems.php ->directory('uploads') ->upload($file, 'profile-picture');
Methods / Accessors
FileS3Like and its repositories (Eg: FileS3LikeSpaces, FileS3LikeGCS)
| Method | Description |
|---|---|
| repository(string $repository): self |
The repository is the storage service you want to use. Supported: spaces, gcs.
|
| disk(string $disk): self | Sets the filesystem disk that the Storage facade will use to handle the files on the cloud storage |
| directory(string $directory): self | The directory in the cloud storage bucket that will be handled. Important: It will concat with the folder configurated in the file filesystem. The folder configuration, is good to have always the same base directory configured, instead of the "directory()" that can change anytime EG.: if folder was configured to be "public", and the directory "images", the final path will be `public/images`. |
| upload(UploadedFile|string $file, ?string $filename = null): DiskFile | Upload the file to the storage. If $filename is empty, the name of the file will be aUUID hash. |
| save(string $repository): DiskFile | Upload and update the file on the storage disk. For Spaces: Purges the CDN cache. For GCS: Same as upload (GCS requires different API for CDN invalidation). If a file with the same name already exists, it will be overwritten. If $filename is empty, the name of the file will be aUUID hash. |
| presignedUrl(string $filepath, ?string $filename = null, int $expiration = 900, string|null $fileType = null, bool $public = false): object |
Create a presigned URL for direct upload to the path in $filepath (relative to the configured folder).
$filename is optional and defaults to a UUID; extension is inferred from $fileType or the filename.
$fileType accepts a mime type or extension (eg: image/png, jpg, image/*) and is used to set Content-Type.
$public toggles the ACL between private (default) and public-read (Note: GCS presigned URLs handle public access differently, but the flag sets the ACL header if supported).
$expiration is in seconds; default is 900 (15 minutes).
|
| purge(string $filepath): self | Purges a CDN cache of a file. Spaces: Calls DigitalOcean CDN API. GCS: No-op (use Google Cloud CDN invalidation API separately). |
| delete(string $filepath): self | Delete a file from the cloud storage disk |
| deleteDirectory(string $filepath): self | Recursively delete a directory from the cloud storage disk |
| directories(string $filepath): array | List directories in the directory set |
| files(string $filepath): array | List files in the directory set |
Presigned URL usage
Use presignedUrl when you need a temporary URL for clients to upload directly to the bucket.
use AndreInocenti\LaravelFileS3Like\Facades\FileS3Like; $upload = FileS3Like::repository('gcs') // or 'spaces' ->disk('gcs') ->directory('uploads') ->presignedUrl( filepath: 'avatars', // directory inside the configured folder filename: 'profile.png', // optional; defaults to UUID expiration: 600, // seconds fileType: 'image/png', // mime or extension; sets Content-Type public: true, // optional; false keeps it private ); return response()->json($upload);
The returned Fluent object contains the presigned URL and useful metadata:
{
"presigned_url": "https://storage.googleapis.com/...",
"key": "uploads/avatars/profile.png",
"public_url": "https://storage.googleapis.com/your-bucket/uploads/avatars/profile.png",
"expires": "2024-04-30 12:34:56",
"headers": {
"Content-Type": "image/png",
"ACL": "public-read"
},
"accepted_mime": "image/png",
"accepted_ext": "png"
}
Send the provided headers with the upload request to ensure the ACL and mime type are applied.
DiskFile
DiskFile is a DTO class that is created and delivered when the functions upload or save are called. The class contain accessors that returns some file data.
| Method | Description |
|---|---|
| getFilepath(): string | Return the file, filepath without the url. Eg: "some/path/to/file.jpg". |
| getFilename(): string | Return the file name. Eg: "file.jpg". |
| getUrl(): string | Returns the full file url. Eg: "https://somedomain.com/some/path/to/file.jpg". |
| getExtension(): string | Returns the file extension. Eg: "jpg". |