Validating multiple files in array - laravel

I need to validate multiple uploaded files, making sure they are of a specific type and under 2048kb. The below doesn't appear to check all files in the array
'files' and just presumes the posted files of invalid mime type as it seems to be checking the array object and not its contents.
public function fileUpload(Request $request)
{
$validator = Validator::make($request->all(), [
'files' => 'required|mimes:jpeg,jpg,png',
]);
if ($validator->fails())
{
return response()->json(array(
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
), 400); }
}

You can validate files array like any input array in Laravel 5.2. This feature is new in Laravel 5.2.
$input_data = $request->all();
$validator = Validator::make(
$input_data, [
'image_file.*' => 'required|mimes:jpg,jpeg,png,bmp|max:20000'
],[
'image_file.*.required' => 'Please upload an image',
'image_file.*.mimes' => 'Only jpeg,png and bmp images are allowed',
'image_file.*.max' => 'Sorry! Maximum allowed size for an image is 20MB',
]
);
if ($validator->fails()) {
// Validation error..
}

Please try this:
public function fileUpload(Request $request) {
$rules = [];
$files = count($this->input('files')) - 1;
foreach(range(0, $files) as $index) {
$rules['files.' . $index] = 'required|mimes:png,jpeg,jpg,gif|max:2048';
}
$validator = Validator::make($request->all() , $rules);
if ($validator->fails()) {
return response()->json(array(
'success' => false,
'errors' => $validator->getMessageBag()->toArray()
) , 400);
}
}

we can also make a request and validate it.
php artisan make:request SaveMultipleImages
here is the code for request
namespace App\Http\Requests;
use App\Core\Settings\Settings;
use Illuminate\Foundation\Http\FormRequest;
class SaveMultipleImages extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return ['files.*' => "mimes:jpg,png,jpeg|max:20000"];
}
}
and then in controller
public function uploadImage(SaveMultipleImages $request) {
dd($request->all()['files']);
}

Try this way.
// 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 ++;
}
}
if($uploadcount == $file_count){
//uploaded successfully
}
else {
//error occurred
}

Related

Save image path to BD - Laravel 5.8

I am making a form in laravel 5.8 in which I am trying to save the image in a folder and the path in the database.
But just save the image and not the route, I've been searching and haven't found a solution.
The "uploads" folder (folder where images are saved) is located inside the "public" folder.
This is my controller:
public function store(SaveAssistanceRequest $request)
{
if ($request->hasFile('photo')) {
$file = $request->file('photo');
$name = time().$file->getClientOriginalName();
$file->move(public_path().'/uploads/', $name);
}
$assistance= new Assistance();
$assistance->photo = $name;
Assistance::create($request->validated());
return redirect()->route('assistances.index')->with('status',' Assistance was created successfully.
');
}
This file validates the data
class SaveAssistanceRequest extends FormRequest
{
public function authorize()
{
return true;
}
public function rules()
{
return [
'resident_id' => 'required',
'date' => 'required',
'entry_time' => 'required',
'departure_time' => 'required',
];
}
public function messages()
{
return[
'resident_id.required' => 'Assistance needs a resident',
'date.required' => 'Assistance needs a date',
'entry_time.required' => 'Assistance needs one hour of entry',
'departure_time.required' => 'Assistance needs a departure time',
];
}
}
Can anybody help me?
public function store(SaveAssistanceRequest $request)
{
$name='';
if ($request->hasFile('photo')) {
$file = $request->file('photo');
$name = time().$file->getClientOriginalName();
$file->move(public_path().'/uploads/', $name);
}
$assistance=Assistance::create($request->validated());
$assistance->photo = $name;
$assistance->save();
return redirect()->route('assistances.index')->with('status',' Assistance was created successfully.

How to test a fake file upload to a route that validate the file in Laravel?

I'm trying to write a test unit for the route 'store' in my controller, pass a fake file to be tested too through the validator of my method, but all i got is that the data is not a file :
Illuminate\Foundation\Testing\TestResponse {
+baseResponse: Illuminate\Http\JsonResponse {
#data: "{
"message":"The given data was invalid.",
"errors":{"invoice":["The invoice must be a file."]}
}"
Code :
Test :
$data = factory('App\Domain\X\X')->raw(['creator_id' => $user->id]);
$data['invoice'] = UploadedFile::fake()->create('invoice.xlsx');
$response = $this->json('POST', route('x.store', $data));
Controller :
public function store(XXXRequest $request)
{
...
Request :
class XXXRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
'name' => 'required',
'invoice' => 'nullable|file',
];
}
try this:
Test:
$data = factory('App\Domain\X\X')->raw(['creator_id' => $user->id]);
$data['invoice'] = UploadedFile::fake()->create('invoice.xlsx');
$response = $this->json('POST', route('x.store', $data), [
'name' => 'abc',
'invoice' => $data['invoice']
]);
Just create an UploadedFile from a local file and add it to your request:
use Illuminate\Http\UploadedFile;
$filename = public_path('tests/invoice.pdf');
$file = new UploadedFile($filename, 'invoice.pdf', 'application/pdf', filesize($filename), null, true);
$this->post('/', [
'invoice' => $file,
]);
You can read about testing file uploads here or visit official documentation
/**
* Example
*
* #test
*/
public function test_correct_file_uploading(): void
{
// Set fake storage ('local', 's3', etc)
Storage::fake('local');
$response = $this->json('POST', '/path_to_your/controller/method', [
'file' => UploadedFile::fake()->create('invoice.xlsx', 1024)
]);
// Assert response successful
$response->assertSuccessful();
// Assert the file was stored
Storage::disk('local')->assertExists('invoice.xlsx');
}

How can i avoid image required in edit form if image exist in laravel?

I am adding and editing a user with same function (Store), when ever i add a user it asks me image is required but whenever i edit a user which have image it also ask me image is required and i want if a image is already present it wont ask me , please see my above code i had recently changed my code according to Gurpal singh
In my controller
public function rules()
{
$child_details = Children::findOrFail($inputs['id']);
$rules = [
'child_name' => 'required',
'gender' => 'required',
'dob' => 'required',
'current_class' => 'required',
'b_group' => 'required',
'm_tongue' => 'required',
'image' => 'image',
];
if ($child_details->notHavingImageInDb()){
$rules['image'] = 'required|image';
}
return $rules;
}
public function Postchild(Request $request)
{
$data = \Input::except(array('_token')) ;
$validator = \Validator::make($data,$rules);
$inputs = $request->all();
if ($validator->fails())
{
return redirect()->back()->withInput()->withErrors($validator->messages());
}
if(!empty($inputs['id'])){
$child_details = Children::findOrFail($inputs['id']);
}else{
$child_details = new Children;
}
$child_details->parent_id = Auth::User()->id;
$child_details->child_name = $inputs['child_name'];
$child_image = $request->file('image');
if($child_image){
$tmpFilePath = 'uploads/childrens/';
$extension = $child_image->getClientOriginalExtension();
$hardPath = str_slug($inputs['child_name'], '-').'-'.md5(time());
$img = Image::make($child_image);
//$img->resize(180)->save($tmpFilePath.$hardPath.'-b.jpg');
$img->fit(250, 250)->save($tmpFilePath.$hardPath.'.'.$extension);
$child_details->image = $hardPath.'.'.$extension;
}
$child_details->save();
if(!empty($inputs['id'])){
return \Redirect()->route('child_list')->with('success', 'Child has been updated');
}else{
return \Redirect()->route('child_list')->with('success', 'Child has been added');
}
}
You can use Conditionally Adding Rules Not having image in database
Add this in model
public function notHavingImageInDb()
{
return (empty($this->image))?true:false;
}
This is the validation rule request
public function rules()
{
$user = User::find(Auth::id());
$rules = [
'name' =>'required|max:100',
'image' =>'image',
];
if ($user->notHavingImageInDb()){
$rules['image'] = 'required|image';
}
return $rules;
}
Don't forgot to import auth and user model
ie
use App\User;
use Auth;
for more detail click here
You can normally do like below :
$rule = array(
'name' => 'required',
);
if (!empty($inputs['id'])) {
$user = User::findOrFail($inputs['id']);
} else {
$rule["image"] = "required";
$user = new User;
}
It is better to separate them or simply create another function. But you can put an if statement that if the image is in the request or not.
Like this:
if(! isset($data['image'])){ //if the image is not in the request
//Your code
}
else{ //if the image is in the request
//Your code
}
If you want a code for storing, renaming, moving an image feel free to request.
You can use validation's after hook.
public function Postchild(Request $request)
{
//Define your rules
$rules = [
'child_name' => 'required',
'gender' => 'required',
'dob' => 'required',
'current_class' => 'required',
'b_group' => 'required',
'm_tongue' => 'required',
];
//Validate your data
$data = $request->except('_token');
$validator = \Validator::make($data,$rules);
$validator->after(function ($validator) {
//Check the mode of request (Create or Update)
if(!empty($data['id'])){
$child_details = Children::findOrFail($data['id']);
if($child_details->image == null){
$validator->errors()->add('image', 'Image field is required');
}
}
});
if ($validator->fails()) {
return redirect()->back()
->withErrors($validator)
->withInput();
}
}
Just this few lines can solve your problems... You have to check there image have or not.
Rules in a private or protected function
private function validateRequest($request)
{
//This is for Update without required image, this will check that In DB image have or not
$child_image = Children::find($request->id);
$rules = [];
if ($child_image) :
if ($child_image->image == null):
$rules['image'] = 'required|image|max:1999';
endif;
//This is for regular validation
else :
$rules = [
'image' => 'required|image|max:1999',
];
endif;
return $rules;
}

Laravel 5 json response image path is not stored in mysql database

I am sending base64 image along with some form data from postman to laravel 5 with mysql. The code works well and returns the success json as well. All values from json is stored in mysql but the json image path is not stored in database, instead some code is stored in databse.
My actual json response in postman is =>
{"success":{"userid":"4","fname":"s","lname":"s","img":"uploads\/5a3f6218a1ed0.jpg"}}
All above json values are stored in databse but the img json path is not stored, instead following data is stored in database.
/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0VFhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoLCw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs
My Laravel API code is
public function add(Request $request)
{
$validator = Validator::make($request->all(), [
'userid' => 'required',
'fname' => 'required',
'lname' => 'required',
'img' => 'required',
]);
if ($validator->fails()) {
return response()->json(['error'=>$validator->errors()], 401);
}
$input = $request->all();
$user = News::create($input);
$success['userid'] = $user->userid;
$success['fname'] = $user->fname;
$success['lname'] = $user->lname;
if ($user->img)
{
$img2 = $user->img;
$img3 = str_replace('data:image/jpg;base64,', '', $img2);
$img3 = str_replace(' ', '+', $img3);
$data = base64_decode($img3);
$file = 'uploads/' . uniqid() . '.jpg';
file_put_contents($file, $data);
$imgfile = $file;
$success['img'] = $imgfile;
}
return response()->json(['success'=>$success], $this->successStatus);
}
What actually i am missing...
This is because you save record like this:
$user = News::create($input);
so you don't save $imgfile in database.
You can add after:
$success['img'] = $imgfile;
the following line to update record
$user->update(['img' => $imgfile]);
or you can change the order of your code to create News record later with valid img field already.
Also keep in mind you are using wrong variable names. There is no point to have $user variable that holds News model.
As Marcin has stated above it's because you're not saving imgfile into the database.
I would also consider refactoring some of your code so that the add method isn't so verbose. Consider something like the following code block. Please note no use statements have been used an no try/catch has been implemented.
I have also found that it is generally better to give fuller variable and property names. Such as fname I would call first_name/firstName depending on context.
<?php
class ApiController
{
/**
* Add news item
*
* #param Request $request
* #return \Illuminate\Http\JsonResponse
*/
public function add(Request $request)
{
$validator = $this->validateData($request);
if ($validator->fails()) {
return response()->json(['error'=>$validator->errors()], 422);
}
$news = News::create($request->all());
if ($news) {
$success['userid'] = $news->userid;
$success['fname'] = $news->fname;
$success['lname'] = $news->lname;
$success['img'] = $this->uploadImage($news);
$news->update(['img' => $success['img']]);
return response()->json(['success'=>$success], $this->successStatus);
}
return response()->json(['error'=>'An Error occurred when creating the news item'], 422);
}
/**
* Upload Image and return file name
*
* #param $news
* #return string
*/
protected function uploadImage($news)
{
$image = $news->img;
$image = str_replace('data:image/jpg;base64,', '', $image);
$image = str_replace(' ', '+', $image);
$data = base64_decode($image);
$file = 'uploads/' . uniqid() . '.jpg';
file_put_contents($file, $data);
return $file;
}
/**
* Validate inbound request
*
* #param $request
*/
protected function validateData($request)
{
Validator::make($request->all(), [
'userid' => 'required',
'fname' => 'required',
'lname' => 'required',
'img' => 'required',
]);
}
}

Problems creating users in laravel

I am creating the traditional register of users with Laravel and I have a problem to send specific value.
public function postUserRegister(){
$input = Input::all();
$rules = array(
'name' => 'required',
);
$v = Validator::make($input, $rules);
if($v->passes() ) {
$user = User::create(Input::all());
} else {
Session::flash('msg', 'The information is wrong');
return Redirect::back();
}
}
This code works correctly , but I need to send always the same value into table users and this column doesn't appear in the form. How can I send the value of the table if the value doesn't appear?
You can just supply the value manually. There are several ways to do this, here is one:
$user = new User(Input::all());
$user->yourcolumn = $yourdata;
$user->save();
You can use input merge to add extra fields.
Input::merge(array('val_key' => $val_name));
$input = Input::all();
Firstly, I think it would be ideal to clean a bit the method, something like that:
public function postUserRegister(Request $request)
{
$validator = Validator::make($request->all(), [
'name' => 'required'
]);
if ($v->fails()) {
Session::flash('msg', 'The information is wrong');
}
User::create($request->all());
return Redirect::back();
}
And now you can simply assign a data to a specific column by using:
$request->merge(['column_name' => 'data']);
The data can be null, or variable etc. And now the whole code would look something like:
public function postUserRegister(Request $request)
{
$request->merge(['column_name' => 'data']);
$validator = Validator::make($request->all(), [
'name' => 'required'
]);
if ($validator->fails()) {
Session::flash('msg', 'The information is wrong');
}
User::create($request->all());
return Redirect::back();
}
You can add whatever data you want directly into the create method:
public function postUserRegister()
{
$input = request()->all();
if (validator($input, ['name' => 'required'])->fails()) {
return back()->with('msg', 'The information is wrong');
}
$user = User::create($input + ['custom' => 'data']);
//
}
P.S. Merging that data into the request itself is a bad idea.
You can do this in the User model by adding the boot() method.
class User extends Model
{
public static function boot()
{
parent::boot();
static::creating(function ($user) {
$user->newColumn = 'some-value';
});
}
...
}
Reference: https://laravel.com/docs/5.2/eloquent#events

Resources