Amazon S3 remove empty folder from PHP - php

I'm trying to remove objects and when all objects are removed i want to remove the main folder.
right now its work fine when i remove a object key in a folder, and when the folder are empty the folder will be removed, but when i hit the last main folder like (folder1/folder2/) and folder1 one are empty after folder2 are removed, i can't removed this folder.
my php code look like this.
$s3 = new S3Client([
'version' => 'latest',
'region' => AMAZON_S3_REGION,
'credentials' => [
'key' => AMAZON_KEY,
'secret' => AMAZON_SECRET
]
]);
$response = $s3->listObjects([
'Bucket' => AMAZON_S3_BUCKET,
'Prefix' => $prefix_dir
]);
$keys = [];
foreach($response['Contents'] AS $val) {
$keys[]['Key'] = $val['Key'];
}
$result = $s3->deleteObjects([
'Bucket' => AMAZON_S3_BUCKET,
'Objects' => $keys
]);
when i trying to remove the folder path alone after it i get a status-code 204 but why?

Instead of deleteObjects try using deleteMatchingObjects and passing empty prefix or string matching some folder.
$s3->deleteMatchingObjects($bucket);
// or inner of folder
$s3->deleteMatchingObjects($bucket, 'folder1/');

Related

PHP S3 - How to get all versions of a specific file

I have a Laravel project and a version enabled S3 bucket. I can list the versions of all objects within the bucket using the listObjectVersions method.
My attempt to list the versions of a specific object is as follows:
$result = $client->listObjectVersions([
'Bucket' => \Config::get('filesystems.disks.s3.bucket'),
'Key' => $folder . '/' . 'test.png',
]);
This seems to get all objects within the bucket which is not what I want. Is there a way to get just one file?
I am using the AWS PHP SDK.
Thanks
You can use 'Prefix' instead of 'Key':
$client = new S3Client([
'version' => 'latest',
'region' => 'eu-west-1'
]);
$folder = $this->getS3Folder($request, $study);
$result = $client->listObjectVersions([
'Bucket' => \Config::get('filesystems.disks.s3.bucket'),
'Prefix' => $folder . '/' . 'test.png',
]);

How to fix upload image to s3 using Laravel

I try to upload an image to s3 using Laravel but I receive a runtime error. Using Laravel 5.8, PHP7 and API REST with Postman I send by body base64
I receive an image base64 and I must to upload to s3 and get the request URL.
public function store(Request $request)
{
$s3Client = new S3Client([
'region' => 'us-east-2',
'version' => 'latest',
'credentials' => [
'key' => $key,
'secret' => $secret
]
]);
$base64_str = substr($input['base64'], strpos($input['base64'], ",") + 1);
$image = base64_decode($base64_str);
$result = $s3Client->putObject([
'Bucket' => 's3-galgun',
'Key' => 'saraza.jpg',
'SourceFile' => $image
]);
return $this->sendResponse($result['ObjectURL'], 'message.', 'ObjectURL');
}
Says:
RuntimeException: Unable to open u�Z�f�{��zڱ��� .......
The SourceFile parameter is leading to the path of file to upload to S3, not the binary
You can use Body parameter to replace the SourceFile, or saving the file to local temporary and get the path for SourceFile
Like this:
public function store(Request $request)
{
$s3Client = new S3Client([
'region' => 'us-east-2',
'version' => 'latest',
'credentials' => [
'key' => $key,
'secret' => $secret
]
]);
$base64_str = substr($input['base64'], strpos($input['base64'], ",") + 1);
$image = base64_decode($base64_str);
Storage::disk('local')->put("/temp/saraza.jpg", $image);
$result = $s3Client->putObject([
'Bucket' => 's3-galgun',
'Key' => 'saraza.jpg',
'SourceFile' => Storage::disk('local')->path('/temp/saraza.jpg')
]);
Storage::delete('/temp/saraza.jpg');
return $this->sendResponse($result['ObjectURL'], 'message.', 'ObjectURL');
}
And, if you're using S3 with Laravel, you should consider the S3 filesystem driver instead of access the S3Client manually in your controller
To do this, add the S3 driver composer require league/flysystem-aws-s3-v3, put your S3 IAM settings in .env or config\filesystems.php
Then update the default filesystem in config\filesystems, or indicate the disk driver when using the Storage Storage::disk('s3')
Detail see document here
Instead of SourceFile you have to use Body. SourceFile is a path to a file, but you do not have a file, you have a base64 encoded source of img. That is why you need to use Body which can be a string. More here: https://docs.aws.amazon.com/aws-sdk-php/v3/api/api-s3-2006-03-01.html#putobject
Fixed version:
public function store(Request $request)
{
$s3Client = new S3Client([
'region' => 'us-east-2',
'version' => 'latest',
'credentials' => [
'key' => $key,
'secret' => $secret
]
]);
$base64_str = substr($input['base64'], strpos($input['base64'], ",") + 1);
$image = base64_decode($base64_str);
$result = $s3Client->putObject([
'Bucket' => 's3-galgun',
'Key' => 'saraza.jpg',
'Body' => $image
]);
return $this->sendResponse($result['ObjectURL'], 'message.', 'ObjectURL');
}
A very simple way to uploads Any file in AWS-S3 Storage.
First, check your ENV setting.
AWS_ACCESS_KEY_ID=your key
AWS_SECRET_ACCESS_KEY= your access key
AWS_DEFAULT_REGION=ap-south-1
AWS_BUCKET=your bucket name
AWS_URL=Your URL
The second FileStorage.php
'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'),
//'visibility' => 'public', // do not use this line for security purpose. try to make bucket private.
],
Now come on main Code.
Upload Binary File from HTML Form.
$fileName = 'sh_'.mt_rand(11111,9999).".".$imageFile->clientExtension();;
$s3path = "/uploads/".$this::$SchoolCode."/";
Storage::disk('s3')->put($s3path, file_get_contents($req->file('userDoc')));
Upload Base64 File
For Public Bucket or if you want to keep file Public
$binary_data = base64_decode($file);
Storage::disk('s3')->put($s3Path, $binary_data, 'public');
For Private Bucket or if you want to keep file Private
$binary_data = base64_decode($file);
Storage::disk('s3')->put($s3Path, $binary_data);
I Recommend you keep your file private... that is a more secure way and safe. for this, you have to use PreSign in URL to access that file.
For Pre sign-In URL check this post. How access image in s3 bucket using pre-signed url

Delete folder that contains files from s3 bucket php

Im trying to delete a folder in an s3 bucket that is located in a folder called CreativeEngine the folder structure looks like this CreativeEngine/8943
I want to delete the folder with the called 8943 but it contains files within it. Do I need to do some kind of loop to delete the files first or can I delete the folder? I tried this but it didn't work
<?php
$itemId=$_GET['id'];
require('s3/vendor/autoload.php');
use Aws\S3\S3Client;
use Aws\S3\Exception\S3Exception;
// AWS Info
$bucketName = 'mybucket';
$IAM_KEY = 'mykey';
$IAM_SECRET = 'mysecret';
// Connect to AWS
$s3 = S3Client::factory(
array(
'credentials' => array(
'key' => $IAM_KEY,
'secret' => $IAM_SECRET
),
'version' => 'latest',
'region' => 'us-east-2'
)
);
$s3Destination='CreativeEngine/'.$itemId;
$keyName = $s3Destination;
try{
$s3->deleteObject(array(
'Bucket' => $bucketName,
'Key' => $keyName
));
} catch (S3Exception $e) {
$data['message']='<li>error'.$e->getMessage().'</li>';
}
?>
This is possible via delete_all_objects($bucket, $pcre), where $pcreis an optional Perl-Compatible Regular Expression (PCRE) to filter the names against (default is PCRE_ALL, which is "/.*/i"), e.g.:
$s3 = new AmazonS3();
$response = $s3->delete_all_objects($bucket, "#myDirectory/.*#");

PHP S3 deleteBucketAsync wierd working

I have a little problem with AWS S3 service. I'm trying to delete whole bucket and i would like to use deleteBucketAsync().
My code:
$result = $this->s3->listObjects(array(
'Bucket' => $bucket_name,
'Prefix' => ''
));
foreach($result['Contents'] as $file){
$this->s3->deleteObjectAsync(array(
'Bucket' => $bucket_name,
'Key' => $file['Key']
));
}
$result = $this->s3->deleteBucketAsync(
[
'Bucket' => $bucket_name,
]
);
Sometimes this code works and delete whole bucket in seconds. But sometimes it doesn't.
Can someone please explain me how exacly S3 async functions work?

Make AWS s3 directory public using php

I know there is no concept of folders in S3, it uses a flat file structure. However, i will use the term "folder" for the sake of simplicity.
Preconditions:
An s3 bucket called foo
The folder foo has been made public using the AWS Management Console
Apache
PHP 5
Standard AWS SDK
The problem:
It's possible to upload a folder using the AWS PHP SDK. However, the folder is then only accessible by the user that uploaded the folder and not public readable as i would like it to be.
Procedure:
$sharedConfig = [
'region' => 'us-east-1',
'version' => 'latest',
'visibility' => 'public',
'credentials' => [
'key' => 'xxxxxx',
'secret' => 'xxxxxx',
],
];
// Create an SDK class used to share configuration across clients.
$sdk = new Aws\Sdk($sharedConfig);
// Create an Amazon S3 client using the shared configuration data.
$client = $sdk->createS3();
$client->uploadDirectory("foo", "bucket", "foo", array(
'params' => array('ACL' => 'public-read'),
'concurrency' => 20,
'debug' => true
));
Success Criteria:
I would be able to access a file in the uploaded folder using a "static" link. Fx:
https://s3.amazonaws.com/bucket/foo/001.jpg
I fixed it by using a defined "Before Execute" function.
$result = $client->uploadDirectory("foo", "bucket", "foo", array(
'concurrency' => 20,
'debug' => true,
'before' => function (\Aws\Command $command) {
$command['ACL'] = strpos($command['Key'], 'CONFIDENTIAL') === false
? 'public-read'
: 'private';
}
));
Use can use this:
$s3->uploadDirectory('images', 'bucket', 'prefix',
['params' => array('ACL' => 'public-read')]
);

Categories