How to fix upload image to s3 using Laravel - php

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

Related

Digitalocean Spaces Laravel App - Missing region

I am getting the following error:
Missing required client configuration options: region: (string) A “region” configuration value is required for the “s3” service (e.g., “us-west-2”).
Here is my setup (XXX to hide my creds):
.env file:
DO_SPACES_KEY=XXXXX
DO_SPACES_SECRET=XXXX
DO_SPACES_ENDPOINT=https://nyc3.digitaloceanspaces.com
DO_SPACES_REGION=NYC3
DO_SPACES_BUCKET=XXXX
filesystems.php file (under the disks):
'do_spaces' => [
'driver' => 's3',
'key' => env('XXXXX'),
'secret' => env('XXXXX'),
'endpoint' => env('https://nyc3.digitaloceanspaces.com'),
'region' => env('NYC3'),
'bucket' => env('XXXXXX'),
],
Also in filesystems.php file:
‘cloud’ => env('FILESYSTEM_CLOUD’, 'do_spaces’),
in the view file:
function addDocument(Request $req, $projId)
{
$image = $req->file('uploadFile');
$file_name = pathinfo($image->getClientOriginalName(), PATHINFO_FILENAME);
$input['imagename'] = $file_name.'_'.time().'.'.$image->getClientOriginalExtension();
//$destinationPath = public_path('/images');
//$image->move($destinationPath, $input['imagename']);
$destinationPath = $image->store('/', 'do_spaces');
Storage::setVisibility($destinationPath, 'public');
//$data = array('fid'=>$folderId,'fileLoc'=>$input['imagename'],'projId'=>$projId);
//\DB::table('documents')->insert($data);
return back();
}
As you can see in the view, I try to store the image on the space and then store the path in the DB which would represent the path to the space.
I cannot get this error to go away; do you see any issues?
Thanks!
'region' => env('NYC3'), should be 'region' => env('DO_SPACES_REGION'),

Blob upload to s3 with cropme.js

I really need some help with this. I have never used blob as a resource before but I need to use cropme.js and it only outputs the file uploaded as a blob or base64. Here is the github repo for it: https://github.com/shpontex/cropme. I have it working 100% on my side and it gives me the output but I do not know how to go from here. I have tried to upload the blob as a file to Amazon S3 but all it does is save the file to S3 without an extension and when you try to open it, it is a the blob link. Which is useless because the blob will be removed once the browser is cleared. Uploading the base64 route does the same. I just need some direction here please.
Here is the function in app.js from cropme that gives the result:
let img = document.getElementById('cropme-result')
this.position = this.cropme.position()
this.cropme.crop({
type: 'blob', <-- here you can set it to either 'blob' or 'base64'
width: 600
}).then(function(res) {
img.src = res
document.getElementById('croppedimage').src = img.src
})
},
Here is part of the code which uploads the file to S3:
try {
$imagecropped = $_POST['image'];
$key = 'photos/random';
// S3 details
$s3Client = new S3Client([
'version' => 'latest',
'region' => 'us-west-2',
'credentials' => [
'key' => 'MYKEY',
'secret' => 'MYSECRET',
],
]);
$result = $s3Client->putObject([
'Bucket' => 'uploads',
'ACL' => 'public-read',
'Key' => $key,
'Body' => $imagecropped,
]);

How to upload image to digital Ocean Spaces using AWS SDK for Yii2?

Since Digital Ocean Spaces API is compatible with AWS SDK, how to
upload images to Digital Ocean Spaces programmatically using AWS SDK
for Yii2?
Here my details
Good, we have the following data:
1. endpoint: fra1.digitaloceanspaces.com
2. bucket name: dev-abc
3. api key: xxxxxxxxxxxxx and api secret: xxxxxxx
4. The url that you need to use to deliver assets is https://dev-abc
I have tried with this code whis is not working
$uploader = new FileUpload(FileUpload::S_S3, [
'version' => 'latest',
'region' => 'fra1',
'endpoint' => 'https://fra1.digitaloceanspaces.com',
'credentials' => [
'key' => 'xxxxxxxxxxxxx ',
'secret' => 'xxxxxxx'
],
'bucket' => 'dev-abc'
]);
You can php code to upload image in digital ocean:
Configure a client:
use Aws\S3\S3Client;
$client = new Aws\S3\S3Client([
'version' => 'latest',
'region' => 'us-east-1',
'endpoint' => 'https://nyc3.digitaloceanspaces.com',
'credentials' => [
'key' => getenv('SPACES_KEY'),
'secret' => getenv('SPACES_SECRET'),
],
]);
Create a New Space
$client->createBucket([
'Bucket' => 'example-space-name',
]);
Upload Image
$client->putObject([
'Bucket' => 'example-space-name',
'Key' => 'file.ext',
'Body' => 'The contents of the file.',
'ACL' => 'private'
]);
Here how i mange to go this
Added the three libraries gulp,gulp-awspublish,gulp-rename
var gulp = require('gulp');
var awspublish = require('gulp-awspublish');
var rename = require('gulp-rename');
var publisherDev = awspublish.create({
region: 'fra1',
params: {
Bucket: 'dev-static-abc-ro'
},
accessKeyId: 'XCCCCCZX',
secretAccessKey: 'EDKDJKJDKDJ',
endpoint: 'fra1.digitaloceanspaces.com'
});
Now added the function
// dev server
gulp.task('dev', function() {
// console.log("Hi! I'm Gulp default task root!");
return gulp
.src('./temp-dist/**')
.pipe(
rename(function(path) {
path.dirname += '/assets';
// path.basename += "-s3";
})
)
.pipe(publisherDev.publish())
.pipe(publisherDev.sync('assets/'))
.pipe(awspublish.reporter());
});
Run the command
gulp dev
Install composer from https://getcomposer.org/download/ and then run the following to setup the AWS PHP dependencies:
composer require aws/aws-sdk-php
The following code has a form for uploading images, the code processes the files and uploads them to DO Spaces. Replace your values with those in the code.
<?php
require 'vendor/autoload.php';
use Aws\S3\S3Client;
if(isset($_FILES['image'])){
$file_name = $_FILES['image']['name'];
$temp_file_location = $_FILES['image']['tmp_name'];
$s3 = new Aws\S3\S3Client([
'region' => '-- your region --',
'version' => 'latest',
'credentials' => [
'key' => "-- access key id --",
'secret' => "-- secret access key --",
]
]);
$result = $s3->putObject([
'Bucket' => '-- bucket name --',
'Key' => $file_name,
'SourceFile' => $temp_file_location
]);
var_dump($result);
}
?>
<form action="<?= $_SERVER['PHP_SELF']; ?>" method="POST" enctype="multipart/form-data">
<input type="file" name="image" />
<input type="submit"/>
</form>

Uploading file to S3 using presigned URL in PHP

I am developing a Web Application using PHP. In my application, I need to upload the file to the AWS S3 bucket using Presigned URL. Now, I can read the private file from the S3 bucket using pre-signed like this.
$s3Client = new S3Client([
'version' => 'latest',
'region' => env('AWS_REGION', ''),
'credentials' => [
'key' => env('AWS_IAM_KEY', ''),
'secret' => env('AWS_IAM_SECRET', '')
]
]);
//GetObject
$cmd = $s3Client->getCommand('GetObject', [
'Bucket' => env('AWS_BUCKET',''),
'Key' => 'this-is-uploaded-using-presigned-url.png'
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes');
//This is for reading the image. It is working.
$presignedUrl = (string) $request->getUri();
When I access the $presignedUrl from the browser, I can get the file from the s3. It is working. But now, I am uploading a file to S3. Not reading the file from s3. Normally, I can upload the file to the S3 like this.
$client->putObject(array(
'Bucket' => $bucket,
'Key' => 'data.txt',
'Body' => 'Hello!'
));
The above code is not using the pre-signed URL. But I need to upload the file using a pre-signed URL. How, can I upload the file using a pre-signed URL. For example, what I am thinking is something like this.
$client->putObject(array(
'presigned-url' => 'url'
'Bucket' => $bucket,
'Key' => 'data.txt',
'Body' => 'Hello!'
));
How can I upload?
It seems reasonable that you can create a pre-signed PutPobject command by running:
$cmd = $s3Client->getCommand('PutObject', [
'Bucket' => $bucket,
'Key' => $key
]);
$request = $s3Client->createPresignedRequest($cmd, '+20 minutes')->withMethod('PUT');
Then you might want to perform the PUT call from PHP using:
file_put_contents(
$request->getUri(),
'Hello!',
stream_context_create(['http' => [ 'method' => 'PUT' ]])
);
If you want to create a URL that a browser can submit, then you need to have the browser send the file as a form POST. This AWS documentation explains how to create a pre-signed POST request with the fields that you then need to put into an HTML form and display to the user: https://docs.aws.amazon.com/sdk-for-php/v3/developer-guide/s3-presigned-post.html
Also, this answer might be useful: https://stackoverflow.com/a/59644117/53538

The last step of a AWS EC2 to S3 file upload

I have this code :
require '/home/ubuntu/vendor/autoload.php';
$sharedConfig = [
'region' => 'us-west-2',
'version' => 'latest'
];
$sdk = new Aws\Sdk($sharedConfig);
$s3Client = $sdk->createS3();
$result = $s3Client->putObject([
'Bucket' => 'my-bucket',
'Key' => $_FILES["fileToUpload"]["name"],
'Body' => $_FILES["fileToUpload"]["tmp_name"]
]);
It works, basically. It sends a file to S3. But it apparently sends it badly since it always shows as a corrupted file... Can anyone tell me what I am doing wrong?
To be specific - the image I am uploading is a jpg image and when I try to look at it on the S3 instance, I am told that it "cannot be displayed because it contains errors"

Categories