Store S3 URL in database table - php

I'm building a small asset management system in Laravel 5.2
A user can upload images, video etc to the app and the asset meta data gets stored in the assets table. While that's happening, the asset is renamed to match the asset id (I'm storing the original filename too), I'm storing the mime type and uploading the file to S3.
Where I've come unstuck is storing the S3 url in database.
This is my method
public function store(AssetRequest $request)
{
// Initialise new asset and set the name
// from the form
$asset = new Asset(array(
'name' => $request->get('name')
));
$asset->user_id = Auth::user()->id;
// save the asset to the db
$asset->save();
// set the file var = form input
$file = $request->file('asset_path');
$extension = $file->getClientOriginalExtension();
// modify the asset name
$assetFile = $asset->id . '.' . $request->file('asset_path')->getClientOriginalExtension();
// push the new asset to s3
Storage::disk('s3')->put('uploads/' . $assetFile, file_get_contents($file));
$asset->mime = $file->getClientMimeType();
$s3Url = Storage::url($file);
$asset->s3_url = $s3Url;
$asset->original_filename = $file->getClientOriginalName();
$asset->filename = $assetFile;
$asset->file_extension = $extension;
// return ok
$asset->save();
return \Redirect::route('asset.create')->with('message', 'Asset added!');
}
The lines relating to my attempt at storing the S3 url
$s3Url = Storage::url($file);
$asset->s3_url = $s3Url;
Only seems to store a temporary path /storage//tmp/php8su2r0 rather than an actual S3 url. I'd like to avoid having to set the bucket manually, rather hoping I can use what is configured in config/filesystem.php
Any ideas?

you can get everything from the config using the config(key) function helper
so to get the s3 public url of file, do this:
function publicUrl($filename){
return "http://".config('filesystems.disks.s3.bucket').".s3-website.".config('filesystems.disks.s3.region').".amazonaws.com/".$filename;
}
or you can use the underlying S3Client:(taken from here)
$filesystem->getAdapter()->getClient()->getObjectUrl($bucket, $key);

What your are trying to achieve, I have been doing that in many projects.
All you need to do is create image_url column in database. And pass the s3 bucket link + the name of the file + the extension.
You should know the bit that is constant for me like : https://s3-eu-west-1.amazonaws.com/backnine8/fitness/events/ then I have the id and the extension. in your case it could be name and extension.
if(Input::get('file')) {
$extension = pathinfo(Input::get('filename'), PATHINFO_EXTENSION);
$file = file_get_contents(Input::get('file'));
$s3 = AWS::get('s3');
$s3->putObject(array(
'ACL' => 'public-read',
'Bucket' => 'backnine8',
'Key' => '/fitness/events/'.$event->id.'.'.$extension,
'Body' => $file,
));
$event->image_url = 'https://s3-eu-west-1.amazonaws.com/backnine8/fitness/events/'.$event->id.'.'.$extension;
$event->save();
}

Related

Laravel - How to add image file to Firebase cloud storage?

How do I upload images to firebase cloud storage? The documentation gives only these methodes but no upload method. This is the documentation link https://firebase-php.readthedocs.io/en/stable/cloud-storage.html
$storage = $factory->createStorage();
$storageClient = $storage->getStorageClient();
$defaultBucket = $storage->getBucket();
I have seen another stack question related but don't understand the answer.
I would also like to get a link to the stored file.
Thank you in advance!
Check official firebase documentation, as is mentioned there:
"To upload a file to Cloud Storage, you first create a reference to the full path of the file, including the file name."
For example:
// Create a root reference
var storageRef = firebase.storage().ref();
// Create a reference to 'mountains.jpg'
var mountainsRef = storageRef.child('mountains.jpg');
// Create a reference to 'images/mountains.jpg'
var mountainImagesRef = storageRef.child('images/mountains.jpg');
// While the file names are the same, the references point to different files
mountainsRef.name === mountainImagesRef.name // true
mountainsRef.fullPath === mountainImagesRef.fullPath // false
Also, I found another thread here where you can find an example using php
You can do something like this,
$storage = new StorageClient();
$file = fopen($source, 'r');
$bucket = $storage->bucket($bucketName);
$object = $bucket->upload($file, [
'name' => $objectName
]);
printf('Uploaded %s to gs://%s/%s' . PHP_EOL, basename($source), $bucketName, $objectName);
There examples on gcp github repository.
file upload example : here
other examples: here

Getting the file ID of a Created File To Delete- Google Drive API

I'm trying to get the file ID of a created file using the google drive API so I can then use that to delete files. Here is the code:
$file = new Google_Service_Drive_DriveFile();
$file->setName($fileName);
$file->setDescription('Volunteer Hours');
$file->setParents(array($folderId));
$data = file_get_contents($filePath);
$createdFile = $this->service->files->create($file, array(
'data' => $data,
'uploadType' => 'multipart'
));
Is there some kind of .id method where I can say:
$createdFileID = $createdFile.id;
I have looked into the google drive api but wasn't able to find any such method. The reason I want an id for an uploaded file is so I can delete files if I wanted to using that specific id
Ultimately, here is the function I'm trying to write:
// Deletes a specific file from a specific folder
function deleteFile($folderName, $fileID) {
}
This way, we are protected and delete the right file if there happens to be files with the same name in a given folder.
I believe your goal as follows.
You want to retrieve the file ID of the uploaded file on Google Drive using googleapis for php.
When the filename of $fileName is existing in the specific folder of $folderName, you want to delete the existing file.
Answer for Question 1:
In this case, how about the following modification?
From:
$createdFile = $this->service->files->create($file, array(
'data' => $data,
'uploadType' => 'multipart'
));
To:
$createdFile = $this->service->files->create($file, array(
'data' => $data,
'uploadType' => 'multipart'
));
$createdFileID = $createdFile->getId(); // Added
By this, the file ID of the uploaded file can be retrieved with $createdFileID.
Answer for Question 2:
When you want to delete the file using the filename and folder name at function deleteFile($folderName, $fileName) {}, how about the following sample script?
Sample script:
function deleteFile($folderName, $fileName) {
$client = getClient();
$drive = new Google_Service_Drive($client);
$res1 = $drive->files->listFiles(array("q" => "name='{$folderName}' and trashed=false"));
$folderId = $res1->getFiles()[0]->getId();
$res2 = $drive->files->listFiles(array("q" => "name='{$fileName}' and '{$folderId}' in parents and trashed=false"));
if (count($res2->getFiles()) == 0) {
// When the filename of $fileName is not existing,
// do something
} else {
$fileId = $res2->getFiles()[0]->getId();
$drive->files->delete($fileId);
}
}
In this case, when the filename of $fileName is existing in the specific folder of $folderName, the existing file is deleted.
References:
Files: delete
Added:
When you want to delete the file using the file ID, you can use the following script.
function deleteFile($fileID) {
$client = getClient();
$drive = new Google_Service_Drive($client);
$drive->files->delete($fileID);
}
In this case, $folderName is not required to be used. Because at Google Drive, all files has the unique file ID.

how do i upload a file to a directory in google cloud storage using Google_Client library

i want to upload a file to google cloud storage using google client php library on github. Am able to upload file to cloud storage but am not able to upload to a directory in cloud storage. i get the error message No such object: bucketName/abc/test.jpg
$client = new Google_Client();
putenv('GOOGLE_APPLICATION_CREDENTIALS=files/google_cloud.json');
$client->useApplicationDefaultCredentials();
$storage = new Google\Cloud\Storage\StorageClient([
'projectId' => $googleprojectID
]);
$sPath = "files/com/test.jpg";
$objectName = "/abc/test.jpg";
$bucketName = $googlebucketName;
$bucket = $storage->bucket($bucketName);
$bucket->upload( fopen($sPath, 'r') );
$object = $bucket->object($objectName);
$info = $object->update(['acl' => []], ['predefinedAcl' => 'PUBLICREAD']);
First of all, let me share with you this documentation page where you will find the complete reference for the Google Cloud Storage PHP Client Library. More specifically, if you have a look at the upload() method, you will see that in order to set the name of the object uploaded (and therefore its location, given that GCS has a flat namespace), you have to use the options parameter, which can contain a name field pointing to the right location to upload.
Also, note that the correct object name should not start with a slash /, given that it will automatically be added after the bucket name. Therefore, you should modify your code to add something like this:
$sPath = "files/com/test.jpg";
$objectName = "abc/test.jpg"; # Note the removal of "/" here
$options = [
'name' => $objectName
];
$bucketName = $googlebucketName;
$bucket = $storage->bucket($bucketName);
$bucket -> upload(
fopen($sPath, 'r'),
$options
);

Uploading image to web server using FTP

I'm pretty new to laravel and I'm currently stuck at uploading images to web server via ftp. I've followed this article/tutorial to set everything up, but I can't get it to work, I get this error:
Can't write image data to path (/storage/ssd4/849/3099849/ponijeri/public/uploads/1523970289image1.jpg)
Note: I was transferring files/images from my desktop to uploads folder in my project files while the website was still in development (localhost), and everything was working fine until I decided to upload files to my live website on web server.
Controller code:
public function update(Request $request, $id)
{
$findObject = Accommodation::find($id);
$findObject->update($request->all());
Gallery::destroy('objects_id', $id);
foreach ($request['img'] as $img) {
$gallery = new Gallery();
$gallery->objects_id=$id;
$name = time() . $img->getClientOriginalName(); // prepend the time (integer) to the original file name
$img->move('uploads', $name); // move it to the 'uploads' directory (public/uploads)
$gallery->img=$name;
$gallery->save();
// // create instance of Intervention Image
$img = Image::make('uploads/'.$name);
$img->save(public_path().'/uploads/'.$name);
Storage::disk('ftp')->put($gallery, fopen($request->file('img[]'), 'r+'));
}
$headerImage = $request['headerImage'];
$name = time() . $headerImage->getClientOriginalName(); // prepend the time (integer) to the original file name
$headerImage->move('uploads', $name); // move it to the 'uploads' directory (public/uploads)
$findObject->headerImage=$name;
$findObject->save();
// // create instance of Intervention Image
$headerImage = Image::make('uploads/'.$name);
$headerImage->save(public_path().'/uploads/'.$name);
Storage::disk('ftp')->put($headerImage, fopen($request->file('headerImage'), 'r+'));
return redirect('/objects');
}
FTP configuration:
'ftp' => [
'driver' => 'ftp',
'host' => env('FTP_HOST'),
'username' => env('FTP_USERNAME'),
'password' => env('FTP_PASSWORD'),
'root' => '/public/uploads'
],
I appreciate any help!
It seems you are using relative path
public_path()
on production server, please try to use absolute path instead.

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.

Categories