Modifying an uploaded image with ‘wp_get_image_editor’ and ‘wp_handle_upload_prefilter’

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.

3 Answers
3

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);

}

Leave a Comment