How to bulk upload images in Laravel - php

This is the code that i use now, this works for uploading single images, but i want the option to choose multiple images at the same time and upload them to the s3 bucket.
public function create() {
return view(view: 'images.create');
}
public function store(Request $request) {
$path = $request -> file(key: 'image') -> store(path: 'images', options: 's3');
$image = Image::create([
'filename' => basename($path),
'url' => Storage::disk(name: 's3') -> url($path)
]);
return $image;
}
public function show(Image $image) {
return $image -> url;
}
I have been looking into the answer to this question: Uploading multiple files to Amazon S3 from PHP
But struggle to understand and how to implement it into my own code.

Related

I can't see my update profile image using laravel 6

i am trying to update the image of profil ,because to user at the beginning it creates account without image, after it goes the update, so i store the image in root /aswakfolder/public/storage/profiles and i insert image link in db profiles/nameimage.jpeg, i created a function in helpers.php file to display the image its work very will, the problem here is that I do not understand the helpers function, and it does not meet my needs, my need is when image upload and exists it displays my image if not it displays image not-found.jpeg,in my case it always displays not-found.jpeg.
stock image in my folder, and url image insert in db very well.
UsersController.php
public function update(Request $request, $id)
{
$user=User::find($id);
if($request->hasFile('image'))
{
$image = $request->file('image');
$path = $request->image->store('profiles');
$user->image = $path;
}
$request->image = $user->image;
$user->id = Auth::user()->id;
$user->update([
$user->name => $request->name,
$user->email => $request->email,
$user->telephone => $request->telephone,
$user->daten => $request->daten,
$user->country_id=> $request->country_id,
$user->state_id => $request->state_id,
$user->city_id => $request->city_id,
$user->image => $request->image,
]);
session()->flash('success', 'user updated successfully !!');
return redirect('users');
}
helpers.php
function productImage($path)
{
return $path && file_exists('/aswakfolder/public/storage/'.$path) ? asset('/aswakfolder/public/storage/'.$path) : asset('/aswakfolder/public/storage/not-found.jpg');
}
index.blade.php
<div class="inner" style="background-image: url({{ asset(productImage($users->image)) }})">
Make sure you run the commend php artisan storage:link to create the shortcurt on public/ folder.
Documentation

Laravel - Upload Image 404

I want to display an image on my website that i uploaded.
In my database the image is store in local/temp/ i don't know why.
I'm getting a 404 not found error when I want to access to the image
http://projet-site-e-commerceb2.test/storage/uploads/cL9pMFrZO92vliCKvlSgCq64TZOvnG3C2uzxgl6r.jpeg
I did php artisan storage:link to put the storage folder to remain public.
After i uploaded an image, i can see it in public/storage/uploads
HTML
<img src="{{ asset('/storage/' . $product->image)}}" style="height:200" class="card-img-top">
ProdcuctControllerController
public function store(Request $request)
{
$inputs = $request->except('_token');
$product = new Product();
$this->storeImage($product);
foreach ($inputs as $key => $value) {
$product->$key = $value;
}
$product->save();
return redirect('admin/gamelist');
}
public function storeImage($product)
{
if (request()->has('image')){
$product->update([
'image' => request()->image->store('updloads', 'public'),
]);
}
}

Laravel return UploadedFile object instead of image path

In my update method in the controller when i try to dump the requested data
all attributes comes fine but the image printed as object not the imagePath that is saved in the database
Update method
public function update(Request $request, SlideShow $slideshow)
{
$slideshow->update($request->validate([
'title_en' => 'required',
'title_ar' => 'required',
'link' => 'nullable|url',
'image' => 'image'
]));
dd($slideshow);
$slideshow->uploadImage();
session()->flash('success', __('dashboard.slideshow.edit_success'));
return redirect()->route('admin.slideshow.index');
}
SlideShow model
class SlideShow extends Model
{
protected $fillable = ['title_en', 'title_ar', 'link', 'image'];
public function uploadImage($imageName = 'image')
{
if(request()->has($imageName)){
\Storage::delete($this->image);
$uploadedImage = request()->$imageName->store('slideshow/');
\Image::make('storage/'.$uploadedImage)->resize(870, null, function ($constraint) {
$constraint->aspectRatio();
})->save();
$this->update(['image' => $uploadedImage]);
}
}
public static function search($request)
{
return static::where(lang('title'), 'like', '%' . $request->search . '%')->paginate(10);
}
}
This is normal behavior. When the request is made, Laravel converts the files in the request to the UploadedFile class. Since you're accessing the validated data from the request, this is what is returned. You're directly filling these values as attributes, and the UploadedFile doesn't automatically convert to a path, so this should probably not be included in the first update.
Anyway, in your code you're actually including in your question has the dd() method before you call the uploadImage method, and this method saves the path and does not try to safe the entire UploadedFile class. So if you dump it after it probably has the correct value there, can you verify this?
I'd do it like this:
public function update(Request $request, SlideShow $slideshow)
{
// validate first
$data = $request->validate([
'title_en' => 'required',
'title_ar' => 'required',
'link' => 'nullable|url',
'image' => 'image'
]);
// only pull the data that we can update right now
$slideshow->update($request->only(['title_en', 'title_ar','link']));
// handle and store image if needed
$slideshow->uploadImage();
session()->flash('success', __('dashboard.slideshow.edit_success'));
return redirect()->route('admin.slideshow.index');
}
and then the method on the model:
public function uploadImage($imageName = 'image')
{
if(request()->has($imageName)){
\Storage::delete($this->image);
$uploadedImage = request()->$imageName->store('slideshow/');
\Image::make('storage/'.$uploadedImage)->resize(870, null, function ($constraint) {
$constraint->aspectRatio();
})->save();
$this->update(['image' => $uploadedImage->path()]);
}
}

Resized image uploading

I am working on a Laravel application and at some point, when I allow users to upload their own images for different purposes, I want to generate resized previews for these images.
I am uploading all user content to Amazon S3 and the first thing I did about resizing image is uploading the original image, then went through a foreach, resized the image and re-uploaded it to S3.
As you can image, having 4 sizes for each image dramatically increases the upload time and is a performance concern for me.
Here is a code snippet that I use in my upload function:
$storageDriver = Storage::disk('cloud-storage')->getDriver();
$parentSuccess = $storageDriver->put("/$parentId", file_get_contents($file), [
'visibility' => 'public',
'ACL' => 'public-read',
'ContentType' => $contentType,
]);
$ratio = $imageSize[0] / $imageSize[1];
foreach (self::IMAGE_SIZES as $size) {
if ($size > $imageSize[0] || ($size / $ratio) > $imageSize[1]) {
continue;
}
$id = DB::table('storage')->insertGetId([
'content_type' => $contentType,
'parent_id' => $parentId,
'image_width' => $size,
'image_height' => intval($size / $ratio),
]);
$image = Image::make($file)->encode('jpg');
$image->resize($size, null, function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$image->save();
$success = $storageDriver->put("/$id", (string)$image, [
'visibility' => 'public',
'ACL' => 'public-read',
'ContentType' => 'image/jpeg',
]);
if (!$success) {
return null;
}
}
(I know there is a lot of code not included, but it's not relevant).
What method would you choose for handling this in a more efficient way?
Had to implement something like this in my last project, I used Lazy loading. Upload the parent image to s3 and generate the thumbnails only when needed.
You can have the function getThumbnails() attached to the model that has image. The function checks if thumbnails have been generated for that model and returns it, else it generates them.
public function getThumbnails(){
$thumbDir = "path/to/model/thumbnail/dir";
//Check if the folder exists.
//You can also double check if the directory actually has the thumbnails in it
if(!file_exists($thumbDir)){
$this->generateThumbnails($thumbDir);
}
//Return something
}
For more fun, you can be more specific and have a function handle each thumbnail.
public function getThumbnailX(){
$thumb = "path/to/specific/model/thumbnail";
if(!file_exists($thumb)){
$this->generateThumbnailX($thumb);
}
return $thumb;
}
public function getThumbnailX2(){
...
}
Super fun, add it as an attribute of the model.
public function getThumbXAttribute(){
return getThumbnailX();
}
so you can go ahead and call $model->thumbX whenever you need thumbX.
This reduces processing time and also the size of storage required as not all images may have their thumbnail generated.

How To in CakePHP 3: Upload multiple images to server and save each image in database using cakephp 3

I am working on multiple image file uploads using cakephp 3, where, I want those images be uploaded in server as specified in directory path of my code and, each of the uploaded image should be save in database (am using MySQL Database).
On my current build, I can select multiple images in my form, fortunately, after submitting my form, all images are successfully uploaded to server image directory path as I expected, the thing is only one(1) image are saved in database, as it should saved all and each of the images in database.
Herewith a copy of code in my ImageUploadController:
public function add()
{
$UploadedImage = array();
$uploadedImage = $this->UploadedImages->newEntity();
if ($this->request->is('post')) {
$images = array();
$images = $this->request->data['name'];
foreach ($images as $key => $image) {
if(!empty($image[$key].$image['name'])){
$fileName = $image[$key].$image['name'];
$uploadPath = WWW_ROOT.'img/press-releases/';
$uploadFile = $uploadPath.$fileName;
if(move_uploaded_file($image[$key].$image['tmp_name'],$uploadFile)){
$uploadedImage->name = $fileName;
$uploadedImage->image_dir = 'press-releases/';
$uploadedImage->status = $this->request->data['status'];
$this->UploadedImages->save($uploadedImage);
} else { $this->Flash->error(__('Unable to upload image, please try again.')); }
} else { $this->Flash->error(__('Please choose an image to upload.')); }
}//EOF FOREACH
}
$this->set(compact('uploadedImage'));
$this->set('_serialize', ['uploadedImage']);
}
And here is my simple form: add.ctp file:
simple multiple image upload form
And here is my model table UploadImageTable:
class UploadedImagesTable extends Table
{
/**
* Initialize method
*
* #param array $config The configuration for the Table.
* #return void
*/
public function initialize(array $config)
{
parent::initialize($config);
$this->setTable('uploaded_images');
$this->setDisplayField('name');
$this->setPrimaryKey('id');
$this->addBehavior('Timestamp');
}
/**
* Default validation rules.
*
* #param \Cake\Validation\Validator $validator Validator instance.
* #return \Cake\Validation\Validator
*/
public function validationDefault(Validator $validator)
{
$validator
->integer('id')
->allowEmpty('id', 'create');
$validator
->allowEmpty('name');
$validator
->allowEmpty('image_dir');
$validator
->boolean('status')
->allowEmpty('status');
return $validator;
}
}
I am quite new CakePHP 3, so you all guys who knew something about this uploading multiple images and saving each images in a database, please give me a hand or something could help me out of this, coz' am kinda stucked in this thing. Any help from you will be much appreciated.
For more additional details, herewith added a screenshot of my debugger SQL Logs.In the image,I tried to upload 5 images
if you can see the image, as I tried to upload 5 images; at first query it executes an INSERT to my table and then the next other queries are UPDATE, which should be INSERT. I am wondering why DML(Data Manipulation Language)suddenly change in such queries.
more thanks in advance,
Mary
Since you want to save several Images you have to create also multiple Entities to save in your database. With your current Controller you're creating a single Entity and saving the data to this Entity.
In your UploadedImagesController try the following:
public function add()
{
if ($this->request->is('post')) {
$data = $this->request->getData();
$images = $data['name'];
$path = 'img/press-releases/';
foreach ($images as $image) {
if(!empty($image['name'])) {
$fileName = $image['name'];
$uploadPath = WWW_ROOT . $path;
$uploadFile = $uploadPath . $fileName;
if(move_uploaded_file($image['tmp_name'], $uploadFile)) {
// Create a new Entity over here for each uploaded image
$uploadedImage = $this->UploadedImages->newEntity();
$uploadedImage->name = $fileName;
$uploadedImage->image_dir = $path;
$uploadedImage->status = $data['status'];
$this->UploadedImages->save($uploadedImage)
} else {
$this->Flash->error(__('Unable to upload image, please try again.'));
}
} else {
$this->Flash->error(__('Please choose an image to upload.'));
}
}
}
$this->set(compact('uploadedImage'));
$this->set('_serialize', ['uploadedImage']);
}
You can solve this problem also by saving multiple Entities directly. You may also want to outsource your code to a Model or a Behavior to make it reusable in other Controllers. Like burzum mentioned it could be wise to use a file storage plugin to add things like file hashing and/or unique Ids (eg. UUID). Otherwise you could upload files with the same name...

Categories