How can I save image in subfolder using Amazon aws3 | Laravel - laravel

I am using aws to store my images and the code in the controller looks like this:
Storage::disk('3')->put($file->getClientOriginalName(), fopen($file, 'r+'), 'public');
The images are being saved in my local storage.
Now though, I want to be able to create a subfolder to keep the images organized.
For my case, it is registering a business. Therefore I want the images to be stored in a subfolder containing the appropriate business id. I tried this:
Storage::disk('3')->put($file->getClientOriginalName(), fopen($file, 'r+'), 'public/' . $business->id.
More about the controller is as follows:
$input = $request->all();
$files = isset($input['file']) ? $input['file'] : array ();
$business_names = json_decode($input['business_names'], true);
$business_details = json_decode($input['business_details']);
$share_amount = json_decode($input['share_amount'], true);
$entity = json_decode($input['entity'], true);
$directors = json_decode($input['directors'], true);
$shareholders = json_decode($input['shareholders'], true);
$appointments = json_decode($input['appointments'], true);
$input['user_id'] = Auth::user()->id;
Log::info(Auth::user());
Log::info($request->user());
/* Create Business Record */
$business = new Business;
$business->business_names = json_encode($business_names);
$business->share_amount = $share_amount ?: 0;
$business->entity = $entity ?: '';
$business->business_physical_address = json_encode($business_details->physical_address);
$business->has_business_postal_address = $business_details->has_postal_address;
$business->business_postal_address = json_encode($business_details->postal_address);
$business->user_id = $input['user_id'];
$business->save();
/* Create a new folder in storage/app/files named after the business ID */
Storage::makeDirectory('files/' . $business->id);
/* Upload Files */
// TODO: file storing?
foreach($files as $file) {
if ($file) {
Storage::disk('3')->put($file->getClientOriginalName(), fopen($file, 'r+'), 'public/' . $business->id);
// $file->storeAs('files/' . $business->id, $file->getClientOriginalName());
}
}
When I try to save a business now, I see the following error:
C:\xampp\htdocs\startingabandbaby\vendor\league\flysystem\src\Adapter\Local.php(356):
Illuminate\Foundation\Bootstrap\HandleExceptions->handleError(8,
'Undefined index...', 'C:\xampp\htdocs...', 356, Array)
Since I was able to store images before, I am assuming that it is something to do with concatenating the business id.
How can I create a subfolder with the business id everytime I create a new business and add all the files in that same folder?

As per our discussion, you can use below 2 solutions:
1) put():
$path = Storage::disk('s3')->put(
'/files/'. $business->id, //path you want to upload image to S3
file_get_contents($request->file('file')), //fileContent
'public' //visibility
2) putFileAs(): To achieve the same thing withputFileAs(), I needed to write it as below. 1st parameter expects the directory name, I left it blank as I'm mimicking the directory name in s3 through the filename.
$path = Storage::disk('s3')->putFileAs(
'', // 1st parameter expects directory name, I left it blank as I'm mimicking the directory name through the filename
'/files/'. $business->id,
$request->file('file'), //3rd parameter file resource
['visibility' => 'public'] //options
);
Hope this will helps you!

After some research I ended up with the following:
$directory = 'public/' . $business->id;
Storage::disk()->makeDirectory($directory);
foreach($files as $file) {
if ($file) {
Storage::disk()->put($directory . '/' .$file->getClientOriginalName(), fopen($file, 'r+'));
}
}

Related

laravel tries to store multiple images but only store of them multiple times

I've sending multiple distinct (already checked them) images to server and in laravel controller I have this:
//...
if ($request->has('images')) {
$images = [];
foreach ($request->file('images') as $image){
$img = new \App\Image;
$name = Str::slug($validated['name']).'_'.time().'.'.$image->getClientOriginalExtension();
$folder = '/uploads/images/authors/';
$image->storeAs($folder, $name, 'public');
$img->url = $folder.$name;
array_push($images,$img);
}
$author->images()->saveMany($images);
}
//...
then I look into the destination path in storage and found one of the images repeated multiple time with different names.
so what's the problem?
Make your filename destination unique.
if ($request->has('images')) {
$images = [];
foreach ($request->file('images') as $image){
$img = new \App\Image;
$name = Str::random(8).'_'.Str::slug($image->getClientOriginalName()).'.'.$image->getClientOriginalExtension();
// Debug:
logger('Received a file named '.$image->getClientOriginalName().' storing as '.$name);
$folder = '/uploads/images/authors/';
$image->storeAs($folder, $name, 'public');
$img->url = $folder.$name;
$images[] = $img;
}
$author->images()->saveMany($images);
}

How to save formdata and this URL into the database .. I can upload the file to the cloudinary

Hiii , I have this formdata with few data and files. I want to store them into my database table.
this is my controller to store into the UserApplyJob model
public function store(Request $request)
{
$file = $request->file('resume');
Cloudder::upload($file->getRealPath(), null, ['resource_type' => 'raw']);
$publicId = Cloudder::getPublicId();
$url =Cloudder::show($publicId, ['resource_type' => 'raw']);
$requestJob = UserApplyJob::create($request->all());
}
You're not persisting it to the db. Try this at the end.
$requestJob->save();
This is from laravel 7.14
if($request->hasFile('cover_image'))
{
// Get the file with extension
$filenameWithExt = $request->file('cover_image')->getClientOriginalName();
//Get the file name
$filename = pathinfo($filenameWithExt, PATHINFO_FILENAME);
//Get the ext
$extension = $request->file('cover_image')->getClientOriginalExtension();
//File name to store
$fileNameToStore = $filename.'_'.time().'.'.$extension;
}
// Save the image to column
$blog->cover_image = $fileNameToStore;

File upload using foreach in Laravel [duplicate]

This question already has an answer here:
File uploading in Laravel
(1 answer)
Closed 3 years ago.
Been working on this problem for 2 days and still cannot figure it out. I am trying to upload multiple files into storage in my Laravel project. I know my code works up to the foreach as I tested this with dd.
My controller:
$files = $request->file('current_plan_year_claims_data_file_1');
$folder = public_path(). "\storage\\$id";
if (!File::exists($folder)) {
File::makeDirectory($folder, 0775, true, true);
}
if (!empty($files)) {
foreach($files as $file) {
Storage::disk(['driver' => 'local', 'root' => $folder])->put($file->getClientOriginalName(), file_get_contents($file));
}
}
I see that you are trying to store the files directly in public folder, but why not use the Storage API of Laravel and use the public disk? You can do something like this to upload the files to the public directory:
$id = 123;
$files = $request->file();
$folder = $id;
if (count($files) > 0) {
foreach ($files as $file) {
$file->store($folder, ['disk' => 'public']);
}
}
And be sure that you have linked the storage path to public:
php artisan storage:link
Focus on $files = $request->file(); line. When you don't pass an argument to file() method, all uploaded file instances are returned. Now when you will loop over the $files array, you will get access to individual uploaded files.
And then you can store the file using your logic, i.e. you can use the original name or whatever else. Even you can use the Storage facade to process the file instance.
i.e. if you want to store the files with their original names, I find this a cleaner way rather than what you are doing:
$id = 123;
$files = $request->file();
$folder = $id;
if (count($files) > 0) {
foreach ($files as $file) {
Storage::disk('public')->putFileAs(
$folder,
$file,
$file->getClientOriginalName()
);
}
}
And as suggested by #cbaconnier, you can use allFiles() method too that's more descriptive:
$files = $request->allFiles();
I hope this helps.
You're trying to iterate over files, and file is just a reference to request->file(), which is a SINGLE UploadedFile object.
As indicated by your comment, you have multiple file inputs with different name attributes, so you can't easily loop over them with one statement, eg: if you had multiple files all uploaded as "attachments[]" as the input name attribute, you could get them all with $request->allFiles('attachments'), however, if you want to keep the input names as they are, this should be close to what you want.
public function foo(Request $request, $id){
$folder = public_path(). "\storage\\$id";
if (!File::exists($folder)) {
File::makeDirectory($folder, 0775, true, true);
}
$files = array();
$files[] = $request->file('current_plan_year_claims_data_file_1');
$files[] = $request->file('prior_plan_year_claims_data_file_1');
$files[] = $request->file('etc_file_whatever');
foreach($files as $file) {
Storage::disk(['driver' => 'local', 'root' => $folder])->put($file->getClientOriginalName(), file_get_contents($file));
}
}
Side note, i'm not sure what you're doing with File and public_path, but if your goal is just to put something in your app storage, something like this should work fine
public function foo(Request $request, $id){
if(!\Storage::exists($id)){
\Storage::makeDirectory($id);
}
$files = array();
$files[] = $request->file('current_plan_year_claims_data_file_1');
$files[] = $request->file('prior_plan_year_claims_data_file_1');
$files[] = $request->file('etc_file_whatever');
foreach($files as $file) {
\Storage::put("$id/" . $file->getClientOriginalFileName(), $file);
}
}

How to upload multiple images and store their name in database with laravel 5.1?

I have created a form for users can upload multiple images,and move uploaded images to 'Upload' folder and store their names in database. This is my code
public function multiple_upload() {
$multiupload = new Multiupload();
// getting all of the post data
$files = Input::file('images');
// Making counting of uploaded images
$file_count = count($files);
// start count how many uploaded
$uploadcount = 0;
foreach($files as $file) {
$rules = array('file' => 'required'); //'required|mimes:png,gif,jpeg,txt,pdf,doc'
$validator = Validator::make(array('file'=> $file), $rules);
if($validator->passes()){
$destinationPath = 'uploads';
$filename = $file->getClientOriginalName();
$upload_success = $file->move($destinationPath, $filename);
$uploadcount ++;
$multiupload->fileimage = $filename;
$multiupload->save();
}
}
if($uploadcount == $file_count){
Session::flash('success', 'Upload successfully');
return Redirect::to('/');
}
else {
return Redirect::to('/')->withInput()->withErrors($validator);
}
}
After upload all images successfully move to 'Uploads' folder but, in database it store only one image name. So how to store all images name in database?
Please help me and thanks you for help.
The reason is that you are reusing the same Multiupload instance in your loop and just overwriting the saved name with the name of next file. You should be creating a new Multiupload instance for every file that gets uploaded.
As #edrzej.kurylo said
You have to add the below line to inside of foreach($files as $file) {
$multiupload = new Multiupload();
Because you are reusing the same Multiupload function again and again. You have to re initialize the Model for every time the loop runs.
You should move your $multiupload = new Multiupload(); into the foreach loop.
foreach($files as $file) {
$multiupload = new Multiupload();
}
I would use for loop in this manner:
if($request->hasFile('images'){
$files = $request->file('images');
for($i=0; $i<count($files); $i++){
$img = new SampleImage();
$name = rand().'.'.$files[$i]->getClientOriginalExtension();
$files[$i]->move('uploads/samples/',$name);
$img->image_name = $name;
$img->save();
}
}

LARAVEL How to get ID value on Auto Increment ID for naming file?

I am trying to renaming uploaded file to same as ID of table Slider for unique name
public function postAddSlider(){
$title = Input::get('title');
$image = Input::file('image');
$link = Input::get('link');
$description = Input::get('description');
$filename = $image->getClientOriginalName(); //<-- i want to change that filename to be id of table Slider
$uploadSuccess = Input::file('image')->move(base_path().'/public/assets/slider/', $filename);
if($uploadSuccess){
$slider = Slider::create(array(
'image' => $uploadSuccess->getRealPath(),
'title' => $title,
'link' => $link,
'description' => $description
));
if($slider){
return Redirect::route('slider-add-get')
->with('message','Slider Added Successfully');
}
}
else{
return Redirect::route('slider-add-get')
->with('message','File Upload Error');
}
}
or do you have other solution to renaming for unique name?
I have no idea what you're schema is like, but if you want to get the id of a model, you have to save it first.
Perhaps you could do something like this:
$slide = new Slide();
$slide->title = Input::get('title');
$slide->url = $temporaryurl;
...etc...
$slide->save();
//once the slide is saved, we can access its id
$slide->url = 'slide-' . $slide->id . $file->getClientOriginalExtension();
$slide->save(); //updates the new url
Or, if you're just looking to generate unique file names, you could use the original filename + the timestamp... Could possibly result in duplicates... very unlikely though (that 2 images would be uploaded with the same filename within the same second).
Or, perhaps, the slide title (stripped of illegal characters, spaces replaced with dashes, etc), plus the timestamp.

Resources