1

I'm trying to validate file types in Laravel like this:

'rules' => ['mimes:pdf,bdoc,asice,png,jpg']

Validation works correctly for pdf, png and jpg but does not work for bdoc or asice files (files with those extensions do not pass validation).

My guess is that it probably does not work for those file types because they are not included in the MIME types shown here: https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types

Am I correct in that assumption? If so, how can I validate these file types?

2 Answers 2

5

You need to create a custom validation rules for that specific file types.

Check the documentations on creating a custom validation here. https://laravel.com/docs/8.x/validation#custom-validation-rules

Update: Added some sample codes.

Validation Rule

<?php

namespace App\Rules;

use Illuminate\Contracts\Validation\Rule;

class AcceptableFileTypesRule implements Rule
{
    protected array $acceptableTypes = [];

    public function __construct(array $acceptableTypes = [])
    {
        $this->acceptableTypes = $acceptableTypes;
    }

    /**
     * @param string $attribute
     * @param \Illuminate\Http\UploadedFile $value
     *
     * @return bool
     */
    public function passes($attribute, $value): bool
    {
        return in_array($value->getClientOriginalExtension(), $this->acceptableTypes);
    }

    public function message(): string
    {
        // Change the validation error message here
        return 'The validation error message.';
    }
}

You can use it like this

[
   'rules' => ['required', new App\Rules\AcceptableFileTypesRule(['pdf,bdoc,asice,png,jpg'])]
]
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks, exactly what I needed!
Illuminate\Contracts\Validation\Rule is now deprecated
1

From the vendor code at vendor\laravel\framework\src\Illuminate\Contracts\Validation\Rule.php, the interface Illuminate\Contracts\Validation\Rule is now deprecated.

namespace Illuminate\Contracts\Validation;

/**
 * @deprecated see ValidationRule
 */
interface Rule
{
....

The interface Illuminate\Contracts\Validation\ValidationRule is now recommended for creating custom validation rules. So, to modify @Luigel's answer, the up-to-date implementation that is tested in Laravel 10 is:

<?php

namespace App\Rules;

use Closure;
use Illuminate\Contracts\Validation\ValidationRule as Rule;

class CustomFileRule implements Rule
{
    protected array $acceptableTypes = [];

    public function __construct(array $acceptableTypes = [])
    {
        $this->acceptableTypes = $acceptableTypes;
    }

    /**
     * @param string $attribute
     * @param \Illuminate\Http\UploadedFile $value
     *
     * @return void
     */
    public function validate($attribute, $value, Closure $fail) : void
    {
        if(!in_array($value->getClientOriginalExtension(), $this->acceptableTypes)) 
        {
            $fail('Invalid document type uploaded');
        }
    }
}

Notice that it uses the Closure feature of PHP introduced in PHP 5.3 to report error messages.

The instantiation of the class remains the same:

[
   'rules' => ['required', new App\Rules\CustomFileRule(['pdf,bdoc,asice,png,jpg'])]
]

NB: Take care to set the encoding type of your form to enctype="multipart/form-data" before testing this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.