Support » Plugin: Contact Form 7 » image dimension restrictions

  • IT Hertz

    (@it-hertz)


    File size limit is working, but I need restrictions on the dimensions of submitted images.

    I tried this snippet that I found online — slightly modded by me to include max dimensions — but it isn’t working. It returns the correct randomized filename with $file['tmp_name'] in a string, but it doesn’t grab the dimensions (list($width, $height) = getimagesize( $file['tmp_name'] ); returns null), so no matter what size the image is, the result is the minimum width error on validation.

    add_filter( 'wpcf7_validate_file*', 'custom_cf7_file_validation_filter', 7, 2 );
    add_filter( 'wpcf7_validate_file', 'custom_cf7_file_validation_filter', 7, 2 );
    
    function custom_cf7_file_validation_filter( $result, $tag ) {
       if ( 'test_file' == $tag->name ) {
    	$name = $tag->name;
    	$file = isset( $_FILES[$name] ) ? $_FILES[$name] : null;
    	$minimum = array('width' => '100', 'height' => '50');
    	$maximum = array('width' => '400', 'height' => '150');
    	list($width, $height) = getimagesize( $file['tmp_name'] );
    	if ($width < $minimum['width']) {
                $result->invalidate( $tag, "Minimum image width is {$minimum['width']}px. Your image width is $width px");
            } elseif ($height < $minimum['height']) {
                $result->invalidate( $tag, "Minimum image height is {$minimum['height']}px. Your image height is $height px");
            } elseif ($width > $maximum['width']) {
                $result->invalidate( $tag, "Maximum width is {$maximum['width']}px. Your image width is $width px");
            } elseif ($height > $maximum['height']) {
                $result->invalidate( $tag, "Maximum height is {$maximum['height']}px. Your image height is $height px");
            } 
       }
       return $result;
    }

    Help?

Viewing 15 replies - 1 through 15 (of 16 total)
  • Erik

    (@codekraft)

    ciao @it-hertz,

    you need to check the load/change event on input file.

    check this
    http://jsfiddle.net/4N6D9/1/

    I have the same issue and I managed to check the image size via jQuery (with a differend script than @codekraft ‘s one), and eventually display a custom error message right under the field.
    But what I get is just a deterrent, not an effective invalidation of the field; if visitors ignore my error message, they can submit the form anyway.
    How can we really invalidate the field in the CF7 way so that, if somebody tries to submit a form with low-res images, they cannot?

    ciao @lucari,

    in this case you may want to set the input value to null
    file.value=null

    or invalidate the field
    file.setCustomValidity(“error”)

    and file.reportValidity() to show the error message

    Thread Starter IT Hertz

    (@it-hertz)

    I couldn’t get your code to work. I played around with the fiddle, so I know it works there. I’m sure I’m just doing something stupid simple wrong.

    hi @it-hertz,

    just add to your contact form

    [file fileuploader filetypes:jpg id:uploader]
    <script>
    const _URL = window.URL;
    document.getElementById( 'uploader' ).onchange = function () {
    	let file, img;
    	if ( ( file = this.files[ 0 ] ) ) {
    		img = new Image();
    		img.onload = function () {
    			if ( this.width * this.height < 5000 ) {
    				alert( 'ok' );
    			} else {
    				alert( this.width + ' ' + this.height );
    				this.value=null;
    				this.setCustomValidity( 'error' );
    				this.reportValidity();
    			}
    		};
    		img.onerror = function () {
    			alert( 'not a valid file: ' + file.type );
    		};
    		img.src = _URL.createObjectURL( file );
    	}
    };
    </script>
    [submit "Submit"]

    this is another example i’ve done in the past for a similar question
    https://modul-r.codekraft.it/2021/07/image-preview/

    Since i’ve noticed some issues in the script below (but i can’t change it) i’ve posted a working example on my blog

    ps. when I say, however there were issues I am referring to the fact that validation would not work as intended and the file isn’t set to null because “this” refers to the image and not the input. The fix has to be like this

    this.value=null;
    this.setCustomValidity( 'error' );
    this.reportValidity();

    to

    fileInput.value=null;
    fileInput.setCustomValidity( 'error' );
    fileInput.reportValidity();
    Thread Starter IT Hertz

    (@it-hertz)

    Hi,

    I was hoping to do it with only php, but I will explore your JS method. Thanks.

    Thread Starter IT Hertz

    (@it-hertz)

    I’ve been busy with other things, but am now working on this again to try to complete this form.

    @codekraft snippet works, but I’m having difficulty integrating it with CF7 with regard to custom validation messages and further actions on error. I know JS variables can’t be passed to PHP on the same page, and I don’t want to do weird tricks like store in a cookie, etc. Besides, wouldn’t reloading the form page on submit empty it in the first place? I suppose if an unsucessful submission is captured, it wouldn’t empty, but double loading the page to check the file upload doesn’t seem like the best way and aesthetics would probably suffer. Using other pages outside of the form page would be even more of a mess.

    Meanwhile, I went back to tinkering with the php snippet in the OP and read on stack overflow that getimagesize will not work unless php.ini has allow_url_fopen set to 1 (on), and it’s 0 by default. That would explain why my function always returns null. D’oh!

    Welp, my ISP hides php.ini (there is no cgi-bin folder available, so nothing to upload my own php.ini to, either). It’s only accessible from DirectAdmin and allow_url_fopen is not among the available directives to add. Figures!

    I will contact my ISP about this and see whether they’ll work with me. If I can get them to add this directive, I’ll update the thread as to whether enabling it makes the OP snippet work.

    Thread Starter IT Hertz

    (@it-hertz)

    I found it in a separate PHP settings menu, and it was already enabled, so that’s not why the OP code isn’t working.

    Anybody know how to check/enforce image file dimensions in PHP?

    Erik

    (@codekraft)

    To check the size of an image with php you can use getimagesize

    then if needed you scale down the image with image_resize

    Thread Starter IT Hertz

    (@it-hertz)

    As I indicated, getimagesize is not working, despite allow_url_fopen being enabled. The $width and $height are returned as null using the code in the OP. If that code is flawed, then I need to know why.

    Apologies for not elaborating. Maybe the following will help troubleshoot.

    Here’s an example of what this line: $file = isset( $_FILES[$name] ) ? $_FILES[$name] : null; returns: /tmp/phpYxlUu3

    Is the CF7 temp folder only “tmp” and everything after that is a randomized file name, or is “phpYxlUu3” a randomized subfolder where the actual/normal file name is supposed to be stored?

    That “php” prefix appears on every instance of file attachment. Is that normal behavior, or is flawed code causing “php” to be returned when only “YxlUu3” should be returned?
    I tried stripping “php”, but no joy, $width and $height are still null, and this is apparently due to an invalid file name (nothing to run getimagesize on).

    Erik

    (@codekraft)

    I’m sorry but it had been so long that I had lost the thread of the question… I tried as you suggested in #1 and it needs some modification to make it work, try it like this

    add_filter( 'wpcf7_validate_file*', 'custom_cf7_file_validation_filter', 7, 3 );
    add_filter( 'wpcf7_validate_file', 'custom_cf7_file_validation_filter', 7, 3 );
    
    function custom_cf7_file_validation_filter( $result, $tag, $args ) {
    	$minimum = array('width' => '100', 'height' => '50');
    	$maximum = array('width' => '400', 'height' => '150');
    
    	$args = wp_parse_args( $args, array() );
    
    	if ( empty( $args['uploaded_files'] ) ) {
    		$result->invalidate( $tag, 'no file uploaded' , true);
    	}
    
    	foreach ($args['uploaded_files'] as $file) {
    		$name = $tag->name;
    
    		if (!empty($file)) {
    
    			$filepath = str_replace(ABSPATH, "", $file);
    
    			list($width, $height) = getimagesize( $filepath ) ;
    
    			if ($width < $minimum['width']) {
    				$result->invalidate( $tag, "Minimum image width is {$minimum['width']}px. Your image width is $width px");
    				break;
    			} elseif ($height < $minimum['height']) {
    				$result->invalidate( $tag, "Minimum image height is {$minimum['height']}px. Your image height is $height px");
    				break;
    			} elseif ($width > $maximum['width']) {
    				$result->invalidate( $tag, "Maximum width is {$maximum['width']}px. Your image width is $width px");
    				break;
    			} elseif ($height > $maximum['height']) {
    				$result->invalidate( $tag, "Maximum height is {$maximum['height']}px. Your image height is $height px");
    				break;
    			}
    		}
    	}
    
    	return $result;
    }
    • This reply was modified 1 month ago by Erik.
    Erik

    (@codekraft)

    And about the resize, you may replace the part that checks for the maximum image size with something like this:

    
    ...
    elseif ($width > $maximum['width'] || $height > $maximum['height']) {
    	$image = wp_get_image_editor( $filepath );
    	if ( ! is_wp_error( $image ) ) {
    		$image->resize( 300, 300, true );
    		$image->save( $filepath );
    	}
    }
    ...
    Thread Starter IT Hertz

    (@it-hertz)

    Hi,

    The first snippet works beautifully. Thank you!!

    The second, resizing snippet.. not so much. It is allowing huge images to be submitted and saved to database.

    Erik

    (@codekraft)

    @it-hertz, sorry if i wasn’t clear,
    but the second snippet is intended to replace the section in the first one between the “if ($width > $maximum[‘width’])” and the end of “if($height > $maximum[‘height’])”.

    In that way instead of invalidating the email you will automatically resize the image, hope can be useful!

    • This reply was modified 1 month ago by Erik.
Viewing 15 replies - 1 through 15 (of 16 total)
  • You must be logged in to reply to this topic.