ziben69's avatar

Laravel | File upload validation

Hello again guys, I am trying to validate image upload with code:

PhotoController function store:

public function store(Request $request)
    {
        request()->validate([
            'image' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048', 
        ]);

        if ($request->has('photos')){
            foreach ($request->photos as $photo) {
                $filename = 'img-'.time().'.'.$photo->getClientOriginalExtension();
                $photo->storeAs('public/photos/',$filename);
                Photo::create([
                    'filename' => $filename
                ]);
            }
        }
        return redirect()->action('PhotoController@plist');
    }

Part of blade's view:

@if (count($errors) > 0)
                    <div class="alert alert-danger">
                        <strong>Whoops!</strong> 
         There were problems adding the file.
         <ul>
         @foreach ($errors->all() as $error)
               <li>The size of a single photo should not exceed 1024KB.</li>
         @endforeach
         </ul>
</div>
@endif
@if(session('success'))
      <div class="alert alert-success">
      {{ session('success') }}
      </div> 
@endif

The error appears even when I try to upload a file with a size of 50KB. I am using XAMPP localhost server.

0 likes
14 replies
tykus's avatar

Is the file input called image or photos - you are using both in the validation and controller action logic. Validation will always fail if your input name is photos because image is not in the request

1 like
ziben69's avatar

So my code should looks like:

 request()->validate([
            'photos' => 'required|image|mimes:jpeg,png,jpg,gif,svg|max:2048',
]);

But it still not working... :(

tykus's avatar

Which validation rule is actually failing - you are forcing a potentially incorrect message.

Change this

 @foreach ($errors->all() as $error)
    <li>The size of a single photo should not exceed 1024KB.</li>
@endforeach

with

 @foreach ($errors->all() as $error)
    <li>{{ $error }}</li>
@endforeach

in order to see a useful error message

ziben69's avatar

so error code:

The photos must be an image.
The photos must be a file of type: jpeg, png, jpg, gif, svg.

When I remove this part of code

image|mimes:jpeg,png,jpg,gif,svg

it works, but this is not a good solution.

Oh, after removing part of the code, I tried to upload a file larger than 2048KB and I get an error from laravel:

fopen(C:\xampp\htdocs\project\public): failed to open stream: Permission denied
tykus's avatar

And, what are you attempting to upload?

ziben69's avatar

The photo is called test.JPG and has a size of 5MB, but this is only as part of the test if there is an error. Though a bootstrap alert should appear. This time it was error laravela (black screen)

But it's strange, because without validation I can easily save the file to the database

jove's avatar

What does your form look like?

the must be a file of type error is because the mimes try to guess the file, try to check what the mime of the file is returned as. I had a issue where mimes:csv failed as it guessed it was a txt file all the time.

And you have a permission error, looks like it's not allowed to write to your public folder.

ziben69's avatar

and how to check which mime of the file is returned?

jove's avatar
foreach ($request->photos as $photo) {
  // use dd or something
  dd($photo->getMimeType());
}
ziben69's avatar

Hmm, error:

The "" file does not exist or is not readable.
jove's avatar

Can you share your form? I believe you are not uploading it correctly.

jove's avatar

Yes, could you show your form.

ziben69's avatar

But without validation it works:

Here is my form:

<form action="{{ action ('PhotoController@store')}}" method="POST" enctype="multipart/form-data">
      <input type="hidden" name="_token" value="{{csrf_token() }}"/>
               <div class="form-row">
                      <div class="form-group col-md-12" id="photoInput">
                             <label>Images:</label>
                             <input type="file" id="uploadPhoto" onchange="ValidateSize(this)" name="photos[]" multiple aria-describedby="fileHelp"/>
                      </div>
               </div>
    <input type="submit" value="Dodaj" class="btn btn-primary"/>
</form>

Please or to participate in this conversation.