4

I'm trying to intercept an image upload, resize it and then just let the upload continue.

I'm using the filter wp_handle_upload_prefilter that passes as an argument a single file $FILES array.

I load the image editor with wp_get_image_editor($file['tmp_name']), resize it and save it with a new name. This all works fine and the resized image is created on my tmp folder. All good up to here.

However the goal is to replace the original image with the resized one.

So I alter the $file['name'] and ['tmp_name'] to point to the new file and return the $file. However Wordpress doesn't like it as it thinks I'm performing a file hijack and throws an error "Specified file failed upload test (core file.php L297)"

If I don't alter the $file variable passed initially then I do get a resized image on my tmp folder but the original large size image is uploaded instead of my resized one.

Below the function:

add_filter('wp_handle_upload_prefilter',  array($this, 'upload_image_filter'));

public function upload_image_filter($file) {

    $image_editor = wp_get_image_editor($file['tmp_name']);

    if (!is_wp_error($image_editor)) {

        // Resize to 400px
        $image_editor->resize(400);
        // Generate a new filename with suffix abcd
        $filename = $image_editor->generate_filename('abcd');
        $saved = $image_editor->save($filename);

        // Try to alter the original $file and inject the new name and path for our new image
        $file['name'] = $saved['file'];
        $file['tmp_name'] = $saved['path'];
    }

    // Return the filtered $file variable
    return $file;

I have also tried to use $image_editor->save($file['tmp_name']) to save my resized image over the original one but I still get the same error. File does get overwritten though.

So I have tried to change tmp_name to a new file and overwriting the file itself as well with no luck.

The lines that throw the error from core file.php are:

// A properly uploaded file will pass this test. There should be no 
// reason to override this one.
$test_uploaded_file = 'wp_handle_upload' === $action ? @ is_uploaded_file( $file['tmp_name'] ) : @ is_file( $file['tmp_name'] );
if ( $test_upload && ! $test_uploaded_file ) {
    return call_user_func( $upload_error_handler, $file, __( 'Specified file failed upload test.' ) );
}

I think the upload fails because it is testing my newly created file with is_uploaded_file which checks if the file has been HTTP uploaded. Seeing it was created in the server, it will fail.

The docs for wp handle upload prefilter ( http://codex.wordpress.org/Plugin_API/Filter_Reference/wp_handle_upload_prefilter ) say: " The wp_handle_upload_prefilter provides you with an opportunity to examine or alter the filename before the file is moved to its final location."

I'm out of ideas. If anyone has any I'd love to hear them! Cheers.

9

I decided to approach it differently. Instead of hooking into 'wp_handle_upload_prefilter' and tampering with the $file variable I decided to do the resize after the file is uploaded and after I get the attachment id like this:

public function resize_attachment($attachment_id, $width, $height) {

    // Get file path
    $file = get_attached_file($attachment_id);

    // Get editor, resize and overwrite file
    $image_editor = wp_get_image_editor($file);
    $image_editor->resize(1600, 1600);
    $saved = $image_editor->save($file);

    // We need to change the metadata of the attachment to reflect the new size

    // Get attachment meta
    $image_meta = get_post_meta($attachment_id, '_wp_attachment_metadata', true);

    // We need to change width and height in metadata
    $image_meta['height'] = $saved['height'];
    $image_meta['width']  = $saved['width'];

    // Update metadata
    return update_post_meta($attachment_id, '_wp_attachment_metadata', $image_meta);

}
  • This really sounds like a hacky way to do it. You should really handle this at the time of upload. – Phill Healey Oct 20 '17 at 14:32
  • 4
    so what is your hook? – RobBenz Nov 14 '17 at 13:01
1

This seems overly complex, when Wordpress offers a native function to add image sizes. I know that this adds another file with a different name, but how does it NOT meet your needs?

Function: add_image_size

  • The problem with add_image_size is that it creates a new image size but leaves the original 6000x6000px file intact. The goal is to replace that original 6000px image with my resized image of say 1600px and let that 1600 be the original image. Then all other sizes on add_image_size can be generated based on that 1600px. Edit: I am using add_image_size for other parts of my plugin but for this issue it does not meet my needs. Basically I want to resize the original image if the file is larger than some Px value. The only way is to resize it while it is being uploaded.. – Fred John Nov 11 '14 at 19:17
  • If you really need to get rid of the larger image, take a look at function bulk_resize_handle_upload in plugins.svn.wordpress.org/bulk-resize-media/trunk/… – skim- Nov 11 '14 at 19:27
  • As I posted below, I decided to resize the image after it's uploaded and I get the attachment ID, instead of trying to use the wp_handle_upload_prefilter and tampering with the $file variable. It works fine now although not what I had in mind initially. – Fred John Nov 11 '14 at 20:07
  • There's also an existing plugin called imsanity which will resize images based on max height/width settings with an option to bulk resize images that have already been uploaded. – Robert Went Mar 17 at 15:44
0

The problem is that you were not saving the uploaded image after manipulating it, before returning it to allow WP to finish.

function original_resize( $image_data ){
        //get the orig file in WP image editor

        $image_editor = wp_get_image_editor( $image_data['file'] );
        if ( ! is_wp_error( $image_editor ) ) {
            //we have image so get relevant settings
            if($imgRESIZE == true){

                $w_RESIZE = 500;
                $h_RESIZE = 500;

                //get the dimensions of the original uploaded image
                $sizeORIG = $image_editor->get_size();

                //check if resizing is needed
                if( ( isset( $sizeORIG['width'] ) && $sizeORIG['width'] > $w_RESIZE ) || ( isset( $sizeORIG['height'] ) && $sizeORIG['height'] > $max_height ) ) {
                    //perform the resize
                    $image_editor->resize( $w_RESIZE, h_RESIZE, false );
                    //apply minor compression
                    $image_editor->set_quality(80);
                    //save the image
                    $image_editor->save( $image_data['file'] );
                }
            }
        }
        //return image in same format as received
        return $image_data;
    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.