Store thumbnails and uploads in different directories?

It appears that the thumbnail URLs are generated relatively to the upload folder. So trying to store them outside the uploads folder is not going to be a good idea.

There are hacks to filter the output for functions such as the_post_thumbnail_url(), but considering side issues such as the thumbnails not being able to be deleted, it’s not worth a try.

What i was able to achieve, is to store the generated thumbnails in a different subdirectory, inside the uploads folder, and then protect the original uploads folder by setting the proper rules in the .htaccess file, in case you want to protect them from the visitor, making them forbidden to be accessed directly.

I was able to make a copy of the original generator class in wp-image-editor-gd.php to store the thumbnails in subdirectory. Here is how to do so:

First, we set our own class as the primary image generator:

add_filter('wp_image_editors', 'custom_wp_image_editors');
function custom_wp_image_editors($editors) {
    array_unshift($editors, "custom_WP_Image_Editor");
    return $editors;
}

We then include the necessary classes to be extended:

require_once ABSPATH . WPINC . "/class-wp-image-editor.php";
require_once ABSPATH . WPINC . "/class-wp-image-editor-gd.php";

And finally setting the path:

class custom_WP_Image_Editor extends WP_Image_Editor_GD {
    public function generate_filename($suffix = null, $dest_path = null, $extension = null) {
        // $suffix will be appended to the destination filename, just before the extension
        if (!$suffix) {
            $suffix = $this->get_suffix();
        }
        $dir = pathinfo($this->file, PATHINFO_DIRNAME);
        $ext = pathinfo($this->file, PATHINFO_EXTENSION);
        $name = wp_basename($this->file, ".$ext");
        $new_ext = strtolower($extension ? $extension : $ext );
        if (!is_null($dest_path) && $_dest_path = realpath($dest_path)) {
            $dir = $_dest_path;
        }
        //we get the dimensions using explode
        $size_from_suffix = explode("x", $suffix);
        return trailingslashit( $dir ) . "{$size_from_suffix[0]}/{$name}.{$new_ext}";
    }
}

Now the thumbnails will be stored in different sub-folders, based on their width. For example:

/wp-content/uploads/150/example.jpg
/wp-content/uploads/600/example.jpg
/wp-content/uploads/1024/example.jpg

And so on.

Possible issue

Now there might be an issue when we upload images smaller than the smallest thumbnail size. For example if we upload an image, sized 100x100pixels while the smallest thumbnail size is 150x150, another folder will be created in the uploads directory. This might result in a lot of subdirectories in the uploads directory. I have solved this issue with another approach, in this question.

Leave a Comment