AWS presigned url for assests in S3 bucket - php

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);

Related

Laravel 8 Download file from AWS S3 Buckets

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);
}

How to download a file from URL without showing the full path in laravel?

Download link:-
<a href='"+ downloadlink + '/attachment-download/' + $('#employee_ID').val()+'/'+ res[i].file_name +"'>
Route:-
Route::get('/attachment-download/{id}/{filename}', array(
'uses' => 'AttachmentsController#getDownloadAttachments'
));
Attachment Controller:-
public function getDownloadAttachments($id,$filename){
$file="./img/user-icon.png";
$resource = \Employee::WhereCompany()->findOrfail($id);
$path = $this->attachmentsList($resource);
foreach($path as $index => $attachment){
if ($filename == $attachment['file_name']) {
$filePath = $attachment['url'];
}
}
//return \Response::download($file);
return \Response::download($filePath);
}
File URL Output:-
https://zetpayroll.s3.ap-south-1.amazonaws.com/employees/81/Screenshot%20from%202017-04-26%2015%3A07%3A45.png?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAI57OFN3HPCBPQZIQ%2F20170612%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20170612T144818Z&X-Amz-SignedHeaders=host&X-Amz-Expires=3600&X-Amz-Signature=59ecc4d11b7ed71bd336531bd7f4ab7c84da6b7424878d6487679c97a8c52ca7
In this, if try to download the file by using a static path like
$file="./img/user-icon.png";
return \Response::download($file);
it is downloaded fine. But not possible to downloading file from AWS URL, Please help me how to down file automatically using URL. Or How to get Path from URL in laravel or PHP.
Thank you.
Using the above function all the files are being downloaded. But while trying to open the files, text, pdf, ... files open (.text, .csv, .pdf..) without problem, but images don't.
$fileContent = file_get_contents($filePath);
$response = response($fileContent, 200, [
'Content-Type' => 'application/json',
'Content-Disposition' => 'attachment; filename="'.$filename.'"',
]);
return $response;

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.

Save PHP file_get_contents stream to AWS S3

Im trying to get a remote file (an image) using PHP and then put that image to an S3 Bucket.
It mostly works, except that the file that is uploaded to S3 is empty when downloaded back again.
Here is my code so far:
$src = "http://images.neventum.com/2016/83/thumb100x100/56f3fb1b9dbd6-acluvaq_63324840.png";
$name = md5(uniqid());
$ext = pathinfo($src, PATHINFO_EXTENSION);
$file_content = file_get_contents($src);
$filename = "{$name}.{$ext}";
try {
$file = $this->s3->putObject([
'Bucket' => getEnv('s3bucket'),
'Key' => $filename,
'Body' => $file_content,
'ACL' => 'private'
]);
} catch (S3Exception $e) {
//Catch
}
Hope you can help. Thank you so much in advance.
Update 1:
The problem is not with the ACL (I have tested using "public"), is that the saved object on S3 is not uploded correctly (I think is something to do with the encoding, but have not been able to figure it out)
Once you upload image to S3 bucket it will be private you can't able to download directly. You need to give public read access to make object available for download to users.

Create a Google Drive Spreadsheet from a local CSV file via the Google Drive API

I'm trying to upload a local CSV-file to Google Drive and display it like a Google Spreadsheet there. However, when I go to my Google Drive and click the link to my file, I can only download it, not view it as a spreadsheet. I've tried using the ?convert=true but the file doesn't get converted. I've also tried using application/vnd.google-apps.spreadsheet as the mime type but noting changes or I get a 400 Bad request response.
When I right click the file, I can choose to open with Google Spreadsheets which then displays the file correctly. I can't find anything about this in the current documentation over at Google and searches on google haven't help a whole lot.
What I've done so far is creating a new, empty Google spreadsheet and tried filling it with my CSV file but that gives me a 500 Internal Error.
$file = new Google_DriveFile();
$file->setTitle('Exported data from ' . $this->event->title);
$file->setDescription('Exported data from ' . $this->event->title);
$file->setMimeType( 'text/csv' );
try {
$createdFile = $this->drive->files->insert($file, array(
'data' => $data,
'mimeType' => 'application/vnd.google-apps.spreadsheet'
), array('convert'=>true));
// Uncomment the following line to print the File ID
// print 'File ID: %s' % $createdFile->getId();
$additionalParams = array(
'newRevision' => false,
'data' => $data,
'convert'=>true //no change if this is true or false
);
$newFile = $this->drive->files->get( $createdFile->getId() );
$newFile->setMimeType('text/csv');
$updated = $this->drive->files->update($createdFile->getId(), $newFile, $additionalParams);
preint_r($updated);
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
I've looked at the API for Google Drive but haven't found anything useful. I'm wondering if I should use the Google Spreadsheets API or is the Google Drive API the one to use solely?
Many thanks in advance,
Waldemar
Try the following. It's from the File:insert reference in the Google documentation but I added the convert parameter:
/**
* Insert new file.
*
* #param Google_DriveService $service Drive API service instance.
* #param string $title Title of the file to insert, including the extension.
* #param string $description Description of the file to insert.
* #param string $parentId Parent folder's ID.
* #param string $mimeType MIME type of the file to insert.
* #param string $filename Filename of the file to insert.
* #return Google_DriveFile The file that was inserted. NULL is returned if an API error occurred.
*/
function insertFile($service, $title, $description, $parentId, $mimeType, $filename) {
$file = new Google_DriveFile();
$file->setTitle($title);
$file->setDescription($description);
$file->setMimeType($mimeType);
// Set the parent folder.
if ($parentId != null) {
$parent = new ParentReference();
$parent->setId($parentId);
$file->setParents(array($parent));
}
try {
$data = file_get_contents($filename);
$createdFile = $service->files->insert($file, array(
'data' => $data,
'mimeType' => $mimeType,
'convert' => true,
));
// Uncomment the following line to print the File ID
// print 'File ID: %s' % $createdFile->getId();
return $createdFile;
} catch (Exception $e) {
print "An error occurred: " . $e->getMessage();
}
}
i am try above code it will not working for me
it will just stop after login
just use
$file->setMimeType('application/vnd.google-apps.spreadsheet);
$createdFile = $service->files->insert($file, array(
'data' => $data,
'mimeType' => 'text/csv',
'convert' => true,
));
it will work for me
I have to add another parameters to make it work.
'uploadType' => 'multipart'
$createdFile = $service->files->insert($file,array(
'data' => $data,
'mimeType' => 'text/csv',
'convert' => true,
'uploadType' => 'multipart',
));
Now it's working.

Categories