Store thumbnails and uploads in different directories?

I’ve followed the accepted answer in this question to generate my thumbnails in a custom way.

I extended the image editor class as:

class WP_Image_Editor_Custom extends WP_Image_Editor_GD {
    public function generate_filename($prefix = NULL, $dest_path = NULL, $extension = NULL) {
        // If empty, generate a prefix with the parent method get_suffix().
        if(!$prefix)
            $prefix = $this->get_suffix();

        // Determine extension and directory based on file path.
        $info = pathinfo($this->file);
        $dir  = $info['dirname'];
        $ext  = $info['extension'];

        // Determine image name.
        $name = wp_basename($this->file, ".$ext");

        // Allow extension to be changed via method argument.
        $new_ext = strtolower($extension ? $extension : $ext);

        // Default to $_dest_path if method argument is not set or invalid.
        if(!is_null($dest_path) && $_dest_path = realpath($dest_path))
            $dir = $_dest_path;

        // Return our new prefixed filename.
        return trailingslashit($dir)."{$prefix}/{$name}.{$new_ext}";
    }
function multi_resize($sizes) {
    $sizes = parent::multi_resize($sizes);
    //This will generate proper metadata for thumbnails
    foreach($sizes as $slug => $data)
        $sizes[$slug]['file'] = $slug."https://wordpress.stackexchange.com/".$data['file'];

    return $sizes;
}
}

Now, original uploads will be stored in uploads and the thumbnails will be stored in uploads/thumbnail/, /uploads/medium/ and uploads/large/.

What i want is one of these 2 scenarios:

1- to store original uploads in a subfolder such as uploads/original and the thumbnails in uploads/thumbnail/, /uploads/medium/ and uploads/large/.

2- to store the original images in uploads/ and the thumbnails in a folder named thumbs/, OUTSIDE the upload directory, in the root.

I was able to achieve number 2, However, when i call a function such as wp_get_attachment_image_src() it will append my custom thumbnail link (stored in post metadata) to the upload directory, producing a link like:

http://example.com/uploads/thumbs/medium/image.jpg

The correct format must be like:

http://example.com/thumbs/medium/image.jpg

Is it possible to overwrite the metadata while being called to point to the proper file??

2 Answers
2

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