I am trying to run a copy of a website locally but for some reason none of the images work. They are stored on an S3 bucket.
In my config/filesystems.php the default is s3:
'default' => 's3',
My keys are the same as on the live site:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID', 'key'),
'secret' => env('AWS_SECRET_ACCESS_KEY', 'key'),
'region' => 'eu-central-1',
'bucket' => 'storage.website.nl',
'cloud' => 'cloud.website.nl'
],
],
The only difference is my storage/app does not have a public folder with all the media in it like on the live site. But this should be created I think with something similar like php artisan storage:link except this command does not work in laravel 5.2.
What can I do to fix that?
This is my config/filesystems.php file.
'default' => env('FILESYSTEM_DRIVER', 's3'),
'disks' => [
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
],
'b2' => [
'driver' => 's3',
'key' => env('B2_KEY_ID'),
'secret' => env('B2_APP_KEY'),
],
]
How can I get default filesystem's key value?
I think this is possible.
config("filesystems.disks." . config("filesystems.default") . ".key");
I believe there is any better way.
Can anyone help me?
If you want to change config value you should call config helper function and pass the value you want to set as the second argument. You can check it in Laravel documentation
I'm using laravel 5.6 and i wanted to create my custom disk for uploading images
and i received this error
InvalidArgumentException Driver [] is not supported.
this is how i save file in controller
$cover = $request->file('cover_image');
$extension = $cover->getClientOriginalExtension();
Storage::disk('test')->put($cover->getFilename().'.'.$extension, File::get($cover));
this is my config/filesystems.php
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'test' => [
'driver' => 'local',
'root' => storage_path(),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public/asghar'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET'),
'url' => env('AWS_URL'),
],
the error occurred because my configuration was cached.
probably I accidentally used config:cache or sth similar.
the issue resolved by clearing the config cache using this command
php artisan config:clear
Anyone else had this issue:
I set my filesystems.php config defualt from local to cloud (which is set to my s3) and I get this error with my storage code:
$path = $request->file('avatar')->store('avatars'); -> in my UserController
Error : Driver [] is not supported.
If I leave the filesystems config to stock and just run this code the image uploads to my s3 fine
$path = $request->file('avatar')->store('avatars', 's3'); -> in my UserController
shouldnt $path = $request->file('avatar')->store('avatars'); run to what ever the default is without passing the specific driver? I tried 'default' => 's3', and that gets the same error
CONFIG DRIVERS
'default' => 'local',
'cloud' => 's3',
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL').'/storage',
'visibility' => 'public',
],
's3' => [
'driver' => 's3',
'key' => env('AWS_KEY'),
'secret' => env('AWS_SECRET'),
'region' => env('AWS_REGION'),
'bucket' => env('AWS_BUCKET'),
],
],
I guess, that whether your example with manually typing a storage to the store() function works well, you can have a problem with storage config.
Could you, please, show your configuration file with storage types?
My Laravel application needs to manipulate files present in multiple buckets simultaneously into a single session. So, I couldn't find a way to change several times the current bucket, since my .env file is like this:
S3_KEY='MY-KEY'
S3_SECRET='MySeCret'
S3_REGION='us-east-1'
S3_BUCKET='my-first-used-bucket'
I found somewhere that I could do this:
Config::set('filesystems.disks.s3.bucket', 'another-bucket');
but It works only once. What I need is something like:
Storage::disk('s3')->put('/bucket-name/path/filename.jpg', $file, 'public');
Where /bucket-name/ could be any bucket that I already create. What can I do? Thanks a lot!
You are correct in that Config::set(); only works once per request. My estimation is that this is done intentionally to stop the kind of thing you are attempting to do in your code example.
In config/filesystems.php you can list any number of "disks". These are locations of your file repositories. It looks like so:
'disks' => [
'local' => [
'driver' => 'local',
'root' => storage_path('app'),
],
'ftp' => [
'driver' => 'ftp',
'host' => 'ftp.example.com',
'username' => 'your-username',
'password' => 'your-password',
// Optional FTP Settings...
// 'port' => 21,
// 'root' => '',
// 'passive' => true,
// 'ssl' => true,
// 'timeout' => 30,
],
's3' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => env('S3_BUCKET',''),
],
]
The Solution
The solution is to create a new disk of the extra buckets you want to use. Treat your buckets like different disks.
Note: The user that the S3_Key belongs to needs to have permissions to perform your required actions on the S3 buckets you are setting up as additional 'disks'.
'disks' => [
//All your other 'disks'
...
//My default bucket details.
's3' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => env('S3_BUCKET',''),
],
's3MyOtherBucketName' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => 'myOtherBucketName',
],
's3YetAnotherBucketName' => [
'driver' => 's3',
'key' => env('S3_KEY',''),
'secret' => env('S3_SECRET',''),
'region' => env('S3_REGION',''),
'bucket' => 'yetAnotherBucketName',
],
]
Then whenever you want to access the bucket of your choice call it like so:
Storage::disk('s3')->put($fileName, $data);
Storage::disk('s3MyOtherBucketName')->put($anotherFileName, $moreData);
Storage::disk('s3YetAnotherBucketName')->put($yetAnotherFileName, $evenMoreData);
If you have dynamic buckets you also can create a new instance like this:
$storage = Storage::createS3Driver([
'driver' => 's3',
'key' => 'your-key',
'secret' => 'your-secret',
'region' => 'us-east-1',
'bucket' => $bucketName,
]);
$storage->put('path/to/file.png', $content);
You can add the buckets to the filesystems config like so:
'disks' => [
's3' => [
'bucket1' => [
'driver' => 's3',
'key' => env('AWS_BUCKET1_ACCESS_KEY_ID'),
'secret' => env('AWS_BUCKET1_SECRET_ACCESS_KEY'),
'region' => env('AWS_BUCKET1_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET1_BUCKET'),
'url' => env('AWS_BUCKET1_URL'),
],
'bucket2' => [
'driver' => 's3',
'key' => env('AWS_BUCKET2_ACCESS_KEY_ID'),
'secret' => env('AWS_BUCKET2_SECRET_ACCESS_KEY'),
'region' => env('AWS_BUCKET2_DEFAULT_REGION'),
'bucket' => env('AWS_BUCKET2_BUCKET'),
'url' => env('AWS_BUCKET2_URL'),
],
],
],
Then you can access the server using the following:
\Storage::disk('s3.bucket1')->put('path/to/file.png', $content);
I have created a class for myself and named it StorageProxy. You can find it here.
Let's say you want to work with multiple drivers, one of which is an S3-Compatible Object Storage but you may need to change the storage driver on-the-fly, local for example. No problem, the StorageProxy deals with it! (similar to mc - MinIO Client)
Usage:
StorageProxy::touch(?string $disk, ?string $bucket)->{everyStorageMethod}();
If no disk is specified, it uses the default disk (it's defined in filesystem.php).
Example:
For the local driver our file exists in images/sample.jpg
For s3 driver our file exists in images bucket with the name of sample.jpg
Our filesystem.php file should look like this:
'localhost' => [
'driver' => 'local',
'root' => storage_path('/'),
],
'DO' => [
'driver' => 's3',
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION'),
// No need to specify the `bucket` property here
],
Since it's a proxy class, all Storage methods are available in StorageProxy too. Also, you don't need to remove the bucket name from the file path for s3 disks.
// For local disk
$disk = 'localhost';
StorageProxy::touch($disk)->exists("images/sample.jpg"); // true
// For S3 disk
$disk = 'DO';
StorageProxy::touch($disk)->exists("images/sample.jpg"); // true
StorageProxy::touch($disk, "images")->exists("images/sample.jpg"); // true
StorageProxy::touch($disk, "images")->bucketDetection(false)->exists("images/sample.jpg"); // false - the file path is considered as images/images/sample.jpg
StorageProxy::touch($disk, "images")->exists("sample.jpg"); // true