Laravel 8 Download file from AWS S3 Buckets - php

I have tried a few different methods from various Stackoverflow and I am kinda stumped.
I am trying to return a presigned url so that I can display it to the end user for them to download requested file.
My Code
$this->setDestination($documents->location); // folder/path/to/file
$this->setFileName($documents->name); // filename.pdf, filename.doc, etc
$client = Storage::disk('s3')->getDriver()->getAdapter()->getClient();
$bucket = Config::get('filesystems.disks.s3.bucket');
$command = $client->getCommand('GetObject', [
'Bucket' => $bucket,
'Key' => 'docs/c1e09c74-fe9a-4bd8-b624-99249e7d4f98/123456/123456-1/209999/Document/3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf'
/*
'Key' => $this->getDestination() . $this->getFileName()
*/
]);
$request = $client->createPresignedRequest($command, '+20 minutes');
// Get the actual presigned-url
$presignedUrl = (string)$request->getUri();
It will return a URL as such
https://MYSECRET.s3.us-west-2.amazonaws.com/docs/c1e09c74-fe9a-4bd8-b624-99249e7d4f98/123456/123456-1/209999/Document/3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAZCGODPV3AFHI2YM4%2F20201128%2Fus-west-2%2Fs3%2Faws4_request&X-Amz-Date=20201128T051428Z&X-Amz-SignedHeaders=host&X-Amz-Expires=1200&X-Amz-Signature=0232040d7d9c46a51ee6c9424eec52151f6adc48191357d5022094603cbc58e5
When I visit the URL it will display the following.
NoSuchKeyThe specified key does not exist.docs/c1e09c74-fe9a-4bd8-b624-99249e7d4f98/123456/123456-1/209999/Document/3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf9739CAE34DDF00A89ysmJVtjo8oZ1eckvRAW5autyeRLjjhhHc+xZEdStC2iEthhnRBSZHMBYorOt3RKLaZ/yiCMKOo=
When I view it on the S3 Bucket console I will have the
The Key is showing
docs/c1e09c74-fe9a-4bd8-b624-99249e7d4f98/123456/123456-1/209999/Document/3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf
Object Url as defined
https://MYSECRET.s3-us-west-2.amazonaws.com/docs/c1e09c74-fe9a-4bd8-b624-99249e7d4f98/123456/123456-1/209999/Document/3c0e772b-97cb-4e2e-bc33-fdbfae6a4adc.pdf
What am I missing?

//$filename is file name
Route::get('/user/{$filename}', [UserController::class, 'index']);
public function filedownload($filename){
$headers = ['Content-Type' => 'application/jpeg','Content-
Disposition' =>'attachment; filename=one.png',];
return \Response::make(Storage::disk('s3')->get('foldername/'.$keyid),
200,$headers);
}

Related

Picture being uploaded to Firebase storage using PHP but have to create access token manually to make it visible

I am using PHP to upload image to firebase storage. the picture is being uploaded but it is not being accessible as i have to manually create " access token " to make it accessible.
here is the code im using
$bucketName = "example.appspot.com";
$objectName = 'Photos/test.jpeg';
$storage = new StorageClient();
$bucket = $storage->bucket($bucketName);
$object = $bucket->upload(fopen('sign.jpeg', 'r'),
[
'name' => $objectName
]
);
That is indeed working as expected: since your upload is not going through a Firebase SDK, there is not method to generate a download URL.
The common workaround is to create a signed URL with an expiration time far into the future, which is the closest equivalent that Cloud Storage has to Firebase's download URL.
In addition to #Frank's answer, you could also assign the publicRead ACL to the uploaded file and compose the public URL manually:
$bucketName = "example.appspot.com";
$objectName = 'Photos/test.jpeg';
$storage = new StorageClient();
$bucket = $storage->bucket($bucketName);
$object = $bucket->upload(fopen('sign.jpeg', 'r'), [
'name' => $objectName
'predefinedAcl' => 'publicRead'
]);
$publicUrl = "https://{$bucket->name()}.storage.googleapis.com/{$object->name()}";
I have made an indirect way to generate and store the access token.
$payload = file_get_contents('https://firebasestorage.googleapis.com/v0/b/example.appspot.com/o/Photos%2Fpic.jpeg');
$data = json_decode($payload);
echo $data->downloadTokens;
This code has created the access token and it shows the downloadToken on screen.
Thank you everyone for your answers.

PHP AWS S3 sdk: How to generate pre signed url to upload a file to a folder in the S3 bucket using PHP?

I am trying to create a pre signed url to upload a file to a folder in the S3 bucket using PHP. I am able to generate url to upload in bucket, but couldn't figure out where to mention folder name. Below is my code.
$object = 'test_103.jpg';
$bucket = $config['s3_input']['bucket'];
$expiry = new DateTime('+10 minutes');
$command = $s3_input->getCommand(
'PutObject',
[
'Bucket' => $bucket,
'Key' => $object
]
);
$signedRequest = $s3_input->createPresignedRequest($command,'+10 minutes');
$signedUploadUrl = $signedRequest->getUri();
echo $signedUploadUrl;
In above code how do I pass folder name in which I want to create pre signed url?
S3 does not have the hierarchy/directory structure, so keep that in mind, It becomes important when later you want to "move" or "rename" a "folder" on S3
https://serverfault.com/questions/435827/what-is-the-difference-between-buckets-and-folders-in-amazon-s3
Direct answer for your question : Add the slashes "/" in your "Key" to achieve the effect you want
Also, from the document
$commands[] = $s3Client->getCommand('PutObject', array(
'Bucket' => 'SOME_BUCKET',
'Key' => 'photos/photo01.jpg',
'Body' => fopen('/tmp/photo01.jpg', 'r'),
));

AWS presigned url for assests in S3 bucket

We upload contents to S3 private bucket. After uploading contents we access them through presigned url. MP4, images are working fine when we access that url through the browser. But when we try to access SWFs and PDFs, browser prompts to download content.
And also it won't happen when we try to access assets from public bucket.
Is it default behavior or is there any solution for that?
I check this doc
code to get url
public function getPresignedUrl($filename, $expires,$bucket=NULL)
{
if($bucket==NULL){
$bucket=$this->bucket;
}
$command = $this->getClient()->getCommand('GetObject', ['Bucket' =>$bucket , 'Key' => $filename]);
$request = $this->getClient()->createPresignedRequest($command, $expires);
return (string) $request->getUri();
}
=============================Update 1=================================
We are using 'upload' function of AWS sdk to upload swfs, pdfs and also mp4s.
public function upload($filename, $source, $acl = null, array $options = [])
{
if($this->getClient()->upload(
$this->bucket,
$filename,
$source,
!empty($acl) ? $acl : $this->defaultAcl,
$options
)){
return true;
}else{
return false;
}
}
Thanks
When uploading the file, S3 Client will try to determine the correct content type if one hasn't been set .
If no content type is provided and cannot be determined by the filename, the default content type, "application/octet-stream", will be used, thus the browser promts you to download the file.
have a look at http://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectPUT.html
$s3->create_object($bucket, $file_name, array(
// other things
'contentType' => 'application/pdf',
));
As Vamsi said, I upload content with mime type was fixed my issue.
public function uploadPut($filename, $source, $acl = null,$mime=null,$storage='REDUCED_REDUNDANCY', array $options = []){
$result = $this->getClient()->putObject(array(
'Bucket' => $this->bucket,
'Key' => $filename,
'SourceFile' => $source,
'ContentType' => $mime,
'ACL' => $acl,
'StorageClass' => $storage,
));
}
call function
uploadPut($file->name, $file->name, null, $file->mimeType);

aws-sdk 3 putobject not retrieving the file data PHP

I am trying to read the data from a txt file on my amazon AWS bucket. But the body key in the response array is shown as NULL. My code -
function s3_file_get_contents($path, $private = TRUE, $bucket = '') {
require_once(CODE_BASE_DIR . '/ds_engine/docSuggest/external/aws-sdk-3/aws-autoloader.php');
try {
$s3Client = new Aws\S3\S3Client(array('region' => S3_ENDPOINT_REGION, 'version' => S3_ENDPOINT_VERSION,
'credentials' => array(
'key' => S3_SUGGESTADOC_API_KEY,
'secret' => S3_SUGGESTADOC_API_SECRET,
),
));
$result = $s3Client->getObject(array(
'Bucket' => $private ? S3_BUCKET_DOCSUGGEST : S3_BUCKET_SUGGESTADOC,
'Key' => $path,
));
} catch (Exception $e) {
$error = $e->getMessage();
log_message('ERROR', '['.__FUNCTION__.'] Exception: '.$error);
}
die(print_array($result['body']));
return $error ? $error : $result['body'];
}
The file contains some text but nothing is displayed in the console. Rest assured, I have setup the connection properly and there is no issues in that. I am able to download the file but just not read from it.
P.S - The response metadata has an object URL. Using that the file can be downloaded. So I guess I am hitting the correct path but still no success.
The data is in $result['Body'], not in $result['body'].
Look at the documentation:
http://docs.aws.amazon.com/aws-sdk-php/v2/guide/service-s3.html#downloading-objects
Use var_dump($result) to understand better than structure of the response.

upload video to DailyMotion using GuzzleHttp

I'm trying to upload a video using Laravel and GuzzleHttp to DailyMotion. Here's my code:
$file = "3.mp4";
$fields["file"] = fopen($file, 'rb');
$res = $client->post($upload_url, [
'headers' => ['Content-Type' => 'multipart/form-data'],
$fields
]);
$data3 = $res->getBody();
$response_upload_video = json_decode($data3,true);
echo "<br>Getting dm upload video response: ";
print_r($response_upload_video);
$upload_url is a dynamically generated URL passed by DailyMotion. Upon executing the code above, I'll always get this error:
Production.ERROR: GuzzleHttp\Exception\ClientException:
Client error:
POST
http://upload-02.sg1.dailymotion.com/upload?uuid=werewkrewrewrwer&seal=pppppppppppppppp`resulted
in a 400 Bad Request response:
{"error":"invalid content range","seal":"yyyyyyyyyyyyyyyyyy"}
in /home/vagrant/Code/svc-titus/vendor/guzzlehttp/guzzle/src/Exception/RequestException.php:111
But I can upload video to the same upload URL using Postman, as displayed below:
i don't think you need to specify content-type header guzzle will decide it automatically when you provide it a resource also the path of your video here seems problematic if video is stored at public directory you need to use public_path or respective path helper function to get its physical path
below should work in guzzleHttp 6 check sending form files here
http://docs.guzzlephp.org/en/latest/quickstart.html#uploading-data
$file = "3.mp4";
$res = $client->post($upload_url, [
'multipart' => [
[
'name' => 'file',
'contents' => fopen(base_path($file), 'r') // give absolute path using path helper function
]
]
]);
$data3 = $res->getBody();
$response_upload_video = json_decode($data3,true);
echo "<br>Getting dm upload video response: ";
print_r($response_upload_video);

Categories