Laravel image upload validation - php

I am trying to validate uploaded files using laravel validation but am having issues.
Here is my code:
$this->validate($request, [
'image' =>'mimetypes:image/jpeg,image/png,image/gif',
]);
$avatar = $request->file('image');
$fileName = time(). '.' . $avatar->getClientOriginalExtension();
Image::make($avatar)->resize(300,300)->save( public_path('uploads/avatar/' . $fileName));
$user = Auth::user();
$user->avatar = $fileName;
$user->save();
The issue is when I use a bmp file, I get this error:
Gd error
I am using the Intervention image package. I would rather not switch to the imagick driver.
Any ideas?

Looking at the Intervention package code, you can see two implementations to the processBmp function:
Intervention/Image/Gd/Encoder.php:
protected function processBmp()
{
throw new \Intervention\Image\Exception\NotSupportedException(
"BMP format is not supported by Gd Driver."
);
}
Intervention/Image/Imagick/Encoder.php:
protected function processBmp()
{
$format = 'bmp';
$compression = \Imagick::COMPRESSION_UNDEFINED;
$imagick = $this->image->getCore();
$imagick->setFormat($format);
$imagick->setImageFormat($format);
$imagick->setCompression($compression);
$imagick->setImageCompression($compression);
return $imagick->getImagesBlob();
}
So I think it's safe to say that you can't do it with the GD driver, only with imagick.

Simply use "intervention/image": "~2" or change your driver to Imagick. It is a known issue that GD does not natively support BMP. You can check the issue page on github for details.

Why you don`t use Laravel custom rule for image image?
$this->validate($request, [
'image' =>'image',
]);

hope this solution will fix your error, please try with below logic
public function postUpload(Request $request)
{
$input = $request->all();
$rules = array(
'uploadFile' => 'image|max:8000'
);
$validation = Validator::make($input, $rules);
if ($validation->fails())
{
return array(
'validation_failed' => true,
'errors' => $validation->errors()->toArray()
);
}
$file = $request->uploadFile;
$destinationPath = 'uploads/img';
// Get real extension according to mime type
$ext = $file->extension();
// Hash processed file name, including the real extension
$hashname = date('H.i.s').'-'.md5($request->_token).'.'.$ext;
$upload_success = $request->uploadFile->storeAs($destinationPath, $hashname);
Image::configure(array('driver' => 'imagick'));
$img = Image::make(storage_path() . '/app/uploads/img/' . $hashname);
$img->resize(230, null, function ($constraint) {
$constraint->aspectRatio();
});
$img->save(storage_path() . '/app/uploads/lowres/' .$hashname ,80);
$user_image = new User_images();
$user_image->id_user = Auth::user()->id;
$user_image->handler = $hashname;
$user_image->save();
return array('status' => 'success','message'=> 'Image has been uploaded successfully','file_path'=>'/uploads/'.$hashname);

Related

Laravel, update method not working properly when i want to update image file, img become null

i want to update forums table that contains
fr_user_id
fr_author
fr_title
fr_body
fr_filename
code in my controller :
$request->validate([
'fr_user_id' => 'required',
'fr_author' => 'required',
'fr_title' => 'required',
'fr_body' => 'required'
]);
$input = $request->all();
if ($image = $request->file('fr_filename')){
$destinationPath = public_path('/images');
$imgName = time() . '.' . $image->getClientOriginalExtension();
$image->move($destinationPath, $imgName);
$input['fr_filename'] = "$imgName";
} else {
unset($input['fr_filename']);
}
$forum = Forum::find($id);
$forum->update($input);
return redirect('/user/myforum')->with('success','Update Successfull');
my Routes
Route::match(['put','patch'],'/forum/update/{id}',[ForumController::class,'update'])->name('forum/update');
this code is working but the 'fr_filename' data is become null in my db, what should i do?
Had you checked, file is coming in request?

Laravel malformed UTF-8 characters, possibly incorrectly encoded using image intervention

I have a laravel project that has a image upload. I used image intervention library for uploading. The problem is i got a 500 error and saying Malformed UTF-8 characters, possibly incorrectly encoded. But when I look my directory for saving, the image was saved but the data was not saved to the database. Only the image was saved. Seems like the image save was successful but the request is not. What seems to be the problem?
Controller
public function store(Request $request)
{
$product = new Product;
$validator = \Validator::make($request->all(), [
'product_name' => 'required',
'barcode' => 'required|unique:products',
'price'=> 'required',
'category' => 'required',
'supplier' => 'required',
// 'image' => 'required|image64:jpeg,jpg,png'
]);
if ($validator->fails()) {
$errors = json_encode($validator->errors());
return response()->json([
'success' => false,
'message' => $errors
],422);
} else {
$product->barcode = $request->barcode;
$product->product_name = $request->product_name;
$product->price = $request->price;
$product->quantity = 0;
$product->category = $request->category;
$product->supplier_id = $request->supplier;
//image
$imageData = $request->image;
$fileName = time().'.'. explode('/', explode(':', substr($imageData, 0, strpos($imageData, ';'))) [1])[1];
$product->image = \Image::make($request->image)->save(public_path('img/').$fileName);
$product->save();
broadcast(new ProductsEvent(\Auth::user()->name, 'add', $product))->toOthers();
}
}
Vue component event when form is changed
onFileChange(e) {
let file = e.target.files[0];
console.log(file);
var reader = new FileReader();
reader.onloadend = (file)=>{this.image = reader.result}
reader.readAsDataURL(file);
},
It seems that problem is appearing in your $filename generation.
As long as you have the correct image saved the naming convention is all in your hands.
I'd recommend you to go with simpler approach like
$fileName = now()->timestamp . '_' . $imageData->name; and there would be no need for you to go fancy with the name of the file.
The value of the $imageData can not be predicted and all the operations you execute could lead to that problem.
The question has been already asked Laravel "Malformed UTF-8 characters, possibly incorrectly encoded", how to fix?
--- Edit ---
You can get the filename directly from your javascript as you do all the manipulation at that end so you could for example add this.name = file.name; to your sent data, then in your ajax you can send that data like so -
axios.post('/image/store',{
image: this.image,
imageName: this.name
}).then(response => {...});
in your backend $fileName = now()->timestamp . '_' . $request->imageName;
The problem was this line, I was saving the actual image object in the db.
$product->image = \Image::make($request->image)->save(public_path('img/').$fileName);
I changed it into
$imageData = $request->image;
$fileName = time().'.'. explode('/', explode(':', substr($imageData, 0, strpos($imageData, ';'))) [1])[1];
\Image::make($request->image)->save(public_path('img/').$fileName);
$product->image = $fileName;
$product->save();;

How to delete the image from the storage in laravel?

I am currently trying to delete an image when a user updates his/her post before publishing.
Everything works fine, the image is changed in the database and post page, but I want to delete the previous image.
Here is my controller
public function updatePost(Request $request){
$data = $request->all();
$postid = $request['id'];
$isExist = Post::where('id', $postid)->first();
if($isExist){
if ($request->hasFile('image')) {
$file = $request->File('image');
//Get filename with extension
$fileNameToStoreWithExt = $file[0]->getClientOriginalName();
//Get just filename
$filename = pathinfo($fileNameToStoreWithExt, PATHINFO_FILENAME);
//Get just ext
$extension = $file[0]->getClientOriginalExtension();
//File to store
$fileNameToStore = $filename . '_' . time() . '.' . $extension;
//Upload Image
$path = $file[0]->storeAs('image', $fileNameToStore);
$file[0]->move('storage/image', $fileNameToStore);
File::delete(public_path('storage/image'.$isExist['image']));
Post::where('id', $postid)->update([
'title' => $data['title'],
'category' => $data['category'],
'content' => $data['content'],
'image' => $path
]);
return response()->json([
'status'=>'200',
'response'=> 'successfully updated'
]);
}else{
Post::where('id', $postid)->update([
'title' => $data['title'],
'category' => $data['category'],
'content' => $data['content']
]);
return response()->json([
'status'=>'200',
'response'=> 'successfully updated'
]);
}
}else{
return response()->json([
'error'=> 'post does not exist'
]);
}
}
I used:
File::delete(public_path('storage/image'.$isExist['image']));
but it didn't do the job
my delete function
public function deletePost($id){
$post = Post::where('id',$id)->first();
// dd($post);
if(!$post){
return response()->json([
'status' => '500',
'error' => 'post not found'
]);
}
Storage::disk('public')->delete('/storage/image'. $post['image']);
Post::where('id', $id)->delete();
return response()->json([
'status'=> '200',
'response'=> 'Post successfully deleted'
]);
}
my storage path snapshot
use Illuminate\Support\Facades\Storage;
Storage::delete('file.jpg'); // delete file from default disk
Storage::delete(['file.jpg', 'file2.jpg']); // delete multiple files
Storage::disk('your_disk')->delete('file.jpg'); // delete file from specific disk e.g; s3, local etc
Please refer link https://laravel.com/docs/6.x/filesystem
If you look at laravel file-system documentation you will see there are multiple Disk laravel support. you can used Storage Facades to delete a file from Storage like this
use Illuminate\Support\Facades\Storage;
Storage::disk('local')->delete('folder_path/file_name.jpg');
path should be like this for public directory.
Storage::disk('local')->delete('public/image/'.$filename);
its easy to do an if statement and delete old image on updating! this code is an example edit it to your requirements.
if ($request->hasFile('file')) {
Storage::delete($myImage->file); // If $file is path to old image
$myImage->file= $request->file('file')->store('name-of-folder');
}
Another :
File::delete(public_path('images/'. $oldFilename));
see here : https://laracasts.com/discuss/channels/laravel/delete-old-image-from-public-folder-after-updating
You can use normal PHP delete file keyword #unlink
if (file_exists($image)) {
#unlink($image);
}
You can use File to delete file from specific path
$file= "image path here";
\File::delete($file);
Delete uploaded file from public dir
OR
You can use unlink for the same
$image_path = "image path here";
if (file_exists($image_path)) {
#unlink($image_path);
}
PHP -> unlink

My update function doesn't set values to null after saving

I received help to solve how to delete files uploaded by using the Cakephp Upload package. However, there seems to be a problem with how I update the values of the photo and dir fields. By using unlink I was able to delete the files perfectly, but there seems to be a problem when I try to set the values to null. I made a function to test it out:
public function deletePhoto2($id)
{
// $this->request->allowMethod(['post']);
if ($this->request->is(['patch', 'post', 'put'])) {
$brigada = $this->Brigadas
->findById($id)
->firstOrFail();
$brigada->dir = null;
$brigada->photo = null;
if ($this->Brigadas->save($brigada)) {
$this->Flash->success(__('Your team data has been saved.'));
return $this->redirect(['action' => 'edit', $brigada->id]);
}
$this->set('brigada', $brigada);
}
}
Before saving I find that the value of $brigada->photo and $brigada->dir are null, but values don't save. I have several possibilities that want to explore but my knowledge of PHP is a hindrance:
I may be doing updates wrong. Link
I may need to use the deleteCallback which is documented here, but I don't know how to do it. I figured that it would be with $this->Brigadas->deleteCallback() or something similar, but I'd like to understand an example first, which is why I'm asking. I found no use of these callbacks in any example on the web, and the documentation on events is still a bit esoteric for me.
Here is how BrigadasTable.php is setup to upload files:
// http://josediazgonzalez.com/2015/12/05/uploading-files-and-images/
$this->addBehavior('Josegonzalez/Upload.Upload', [
'photo' => [
'fields' => [
'dir' => 'dir',
'size' => 'photo_size', // defaults to `size`
'type' => 'photo_type', // defaults to `type`
],
'nameCallback' => function ($table, $entity, $data, $field, $settings) {
if ($entity->gvCode){
$array = explode(".", $data['name']);
return strtolower($entity->gvCode) . '_' . date("Ymd-hisa") . '.jpg';
} else{
$array = explode(".", $data['name']);
$newArray = array_pop($array);
return strtolower(join('_', $array)) . '_' . date("Ymd-hisa") . '.jpg';
}
},
'transformer' => function ($table, $entity, $data, $field, $settings) {
$extension = pathinfo($data['name'], PATHINFO_EXTENSION);
// Store the thumbnail in a temporary file
$tmp = tempnam(sys_get_temp_dir(), 'upload') . '.' . $extension;
// Use the Imagine library to DO THE THING
$size = new \Imagine\Image\Box(640, 640);
$mode = \Imagine\Image\ImageInterface::THUMBNAIL_INSET;
$imagine = new \Imagine\Gd\Imagine();
// Save that modified file to our temp file
$imagine->open($data['tmp_name'])
->thumbnail($size, $mode)
->save($tmp);
$filenameTmp = explode('.', $data['name']);
array_pop($filenameTmp);
$filenameTmp = join('_', $filenameTmp) . '.jpg';
// return debug($filenameTmp);
// Now return the original *and* the thumbnail
return [
$data['tmp_name'] => $filenameTmp,
$tmp => 'thumbnail-' . $filenameTmp,
];
},
'deleteCallback' => function ($path, $entity, $field, $settings) {
// When deleting the entity, both the original and the thumbnail will be removed
// when keepFilesOnDelete is set to false
$entity->{$field} = null;
return [
$path . $entity->{$field},
$path . 'thumbnail-' . $entity->{$field}
];
},
'keepFilesOnDelete' => false
]
]);
Thank you!
You can run an update query straight, instead of fetching the record, setting values and saving it.
$query = $this->Brigadas->query();
$query->update()
->set([
'dir' => null,
'photo' => null,
])
->where(<condition>)
->execute();
Incase any of your columns are json,
$query = $this->Brigadas->query();
$query->update()
->set([
'dir = null',
'photo' => null,
])
->where(<condition>)
->execute();

Laravel - Pass uploaded filename to new function

I'm using Laravel 5.3 and need to upload an xml file and then submit the contents to an api. The client wants it as 2 buttons/user functions where the user should first upload the file and then with a second click submit the contents.
The uploading is working fine and the xml reading and submitting to api is also working properly. I just can't get my upload controller to pass the filename over to the submitting controller. There is no need to store the filename for future use and the processes will follow each other - ie user will upload one file and submit, then upload next file and submit.
Any help would be highly appreciated
upload function:
public function handleUpload(Request $request)
{
$file = $request->file('file');
$allowedFileTypes = config('app.allowedFileTypes');
$rules = [
'file' => 'required|mimes:'.$allowedFileTypes
];
$this->validate($request, $rules);
$fileName = $file->getClientOriginalName();
$destinationPath = config('app.fileDestinationPath').'/'.$fileName;
$uploaded = Storage::put($destinationPath, file_get_contents($file->getRealPath()));
if($uploaded) {
$file_Name = ($_FILES['file']['name']);
}
return redirect()->to('/upload');
}
submit function:
public function vendorInvoice()
{
$fileName = $file_Name;
$destinationPath = storage_path('app/uploads/');
$xml = file_get_contents($destinationPath.$fileName);
$uri = "some uri";
try {
$client = new Client();
$request = new Request('POST', $uri, [
'Authorization' => '$username',
'ContractID' => '$id',
'content-type' => 'application/xml'
],
$xml);
$response = $client->send($request);
}
catch (RequestException $re) {
//Exception Handling
echo $re;
}
}

Categories