DEV Community

Tyler Smith
Tyler Smith

Posted on

11

Validating an upload as an image OR a video with Laravel

Laravel's Validator makes it simple to validate a request's file field as an image using the 'image' rule, and you can hack together rules for validating a video by restricting MIME types.

$request->validate([
    'image_upload' => 'image|max:1024',
    'video_upload' => 'mimetypes:video/avi,video/mpeg,video/quicktime|max:102400'
]);
Enter fullscreen mode Exit fullscreen mode

But what happens if you have a single upload field that should accept a video that's up to ten megabytes, or accept an image that's a megabyte or less? That's a lot trickier with Laravel's Validator: there doesn't seem to be an elegant solution for this using Laravel's built-in validation rules.

Thankfully, Laravel allows us to create our own custom validation rules. We can create a custom rule closure that checks if the upload is an image or a video, then validates the rules based on the upload type.

$request->validate([
    'file', // Confirm the upload is a file before checking its type.
    function ($attribute, $value, $fail) {
        $is_image = Validator::make(
            ['upload' => $value],
            ['upload' => 'image']
        )->passes();

        $is_video = Validator::make(
            ['upload' => $value],
            ['upload' => 'mimetypes:video/avi,video/mpeg,video/quicktime']
        )->passes();

        if (!$is_video && !$is_image) {
            $fail(':attribute must be image or video.');
        }

        if ($is_video) {
            $validator = Validator::make(
                ['video' => $value],
                ['video' => "max:102400"]
            );
            if ($validator->fails()) {
                $fail(":attribute must be 10 megabytes or less.");
            }
        }

        if ($is_image) {
            $validator = Validator::make(
                ['image' => $value],
                ['image' => "max:1024"]
            );
            if ($validator->fails()) {
                $fail(":attribute must be one megabyte or less.");
            }
        }
    }
]);
Enter fullscreen mode Exit fullscreen mode

I'll be the first to admit: this code looks pretty inelegant. But it works, and the closure leverages existing Validator rules like 'image' and 'max'.

If you prefer a more object-oriented approach, you could extract this code to a Custom Rule Object, and maybe extract methods for is_video() and is_image(). You could even make the max upload sizes configurable in the Rule object's constructor–the sky is the limit!

Hopefully this post saves you some time if you run into this particular challenge in one of your own projects. Also, please drop a comment if you know a more elegant way of accomplishing this!

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more →

Top comments (3)

Collapse
 
aliadelnour profile image
Ali Nour Al Din

Thx alot ♥

Collapse
 
tylerlwsmith profile image
Tyler Smith

Glad you found it helpful!

Collapse
 
abdullahalhabal profile image
Abdullah Alhabal

thanks

Image of Docusign

🛠️ Bring your solution into Docusign. Reach over 1.6M customers.

Docusign is now extensible. Overcome challenges with disconnected products and inaccessible data by bringing your solutions into Docusign and publishing to 1.6M customers in the App Center.

Learn more