Scotalia's avatar

File Validation within a Media Model

TL;DR; I am trying to find a better way to validate file uploads from within my custom Media model. I have not found a solution using the Laravel docs. What I have works, but seems too manual and cumbersome. I am wondering if there is a more 'laravel' way to solve this.

I am trying to validate file uploads from within a custom Media class. I am not sure if I am overcomplicating this and whether I should even do this in the model or just validate uploads from with in the given Controllers.

I figured since I will be allowing file uploads from various endpoints, thus using various Controllers to validate different types of files (images, video, audio), that having a method on a Media class would make sense.

The way I am trying to make this work is as follows:

View : is a form with file upload

Controller : takes the $request->file('finput-name') and passes to uploadFile($file, $uploadPath, $fileType) via a new Media object (ie $newImage->uploadFile($request->file('finput-name') , $uploadPath, $fileType)

Model : I have 2 methods here: uploadFile() and validateFile()

The uploadFile() method calls validateFile() and if file is validated, will upload the file to Server and DB and then returns the new files ID from the database. The concerns/problem I am having is with the validateFile() method.

I am not sure if I have made the right decision to place this method in the Media Model, or if I should do so in my individual controllers - though this does not seem DRY if i were to have in multiple controllers.

ALSO, and more confusing, is the best way to structure the validateFile() method.

Having the validation in the Model, I have not been able to validate an uploaded file without 'manually' performing checks on format/mime and file size. In other words, I haven't successfully been able to us Validator::make or request()->validate() to perform validation and pass back accurate errors. I've had to do this manually and Validator will not take may $file object and validate it b/c it is not an array. I have not been able to successfully able to cast my $file object to an array using toArray().

I guess in the end, what I am looking for is whether what I have done in my code to validate a file in my Media model is the best way, or if there is a more streamlined approach using more laravel helpers - I am assuming there is, but I have not found it yet. (and yes I did refer to the Docs but I was unable to get it to work based on the provided documentation...maybe I am misunderstanding something in them)

private function validateFile($file, $fileType = 'image') {
        // set DEFAULT value to FALSE
        $validFile = false;
        $validMime = false;
        $validFormat = false;
        $validSize = false; 
        $error = [];

        // IMAGE
        if ($fileType === 'image') {
            // validate for proper MIME TYPE
            if (in_array($file->getMimeType(), config('appvars.files.images.mime_types'))) {
                $validMime = true;
            }
            if ($file->getSize() > 0 && $file->getSize() <= config('appvars.files.images.max_file_size.raw')) {
                $validSize = true;
            }
            // validation is good
            if ($validMime && $validSize) {
              $validFile = true;  
            }
            // MIME validation failed
            if ($validMime === false) {
                $error = [
                    'type' => 'danger',
                    'text' => 'The ' . $fileType . ' must be a ' . implode(', ', config('appvars.files.images.file_formats'))
                ];

                array_push($this->fileErrors, $error);
            }
            // SIZE validation failed
            if ($validSize === false) {
                $error = [
                    'type' => 'danger',
                    'text' => 'The ' . $fileType . ' can be no larger than ' . config('appvars.files.images.file_size.display')
                ];
                array_push($this->fileErrors, $error);
            }
            return $validFile;
        }

        // VIDEO
        if ($fileType === 'video') {
            // validate for an video file

            // check if is an VIDEO file
            // check file size
            // check if valid mime type
        }
        // AUDIO
        if ($fileType === 'audio') {
            // validate for an audio file

            // check if is an AUDIO file
            // check file size
            // check if valid mime type
        }
        // DOCUMENT
        if ($fileType === 'document') {
            // validate for an document file

            // check if is a DOCUMENT file
            // check file size
            // check if valid mime type
        }
    }
0 likes
2 replies
Scotalia's avatar

Thanks for the reply Koramit.

I agree with your logic, but it seems redundant to have the same file validation sprinkled through multiple controllers as opposed to a single method on the media class to do the validating each time a media file is uploaded. I mean the validation is not going to be different from form to form for the media files, so if i ever need to change it, I'd rather do in a single place. But, maybe I'm overthinking this.

I'm building this in a silo and it's great to hear your perspective to make me rethink my process. Again, thanks for the time and reply. It's given me something to think about.

Please or to participate in this conversation.