Alexey
Alexey

Reputation: 363

Redirect twice via htaccess

I'm trying to generate thumbnail images dynamically. There is simplifyed example. User requests /fakeimagespath/image_name.400x400.jpg Where 400x400 is desired thumbnail size. If this image exists in folder /realpath/image_name.400x400.jpg - we show it via .htaccess internal redirect.

If this image not exists I want an internal redirect to /generator.php?name=image_name&size=400x400 This php file will generate it from source file and output with jpeg mime type.

Please help with the mod_revrite rules.

#index.php prints $_SERVER for debug purposes.
#cup.jpg, girl.jpg - existing files, 404.jpg - not exists

RewriteEngine on
RewriteCond $1 ^fakeimage
RewriteRule ^(fakeimage\-(cup|girl|404)\.jpg)$ /realpath/$2.jpg

RewriteCond $1 -f
RewriteRule ^(.*)$ /index.php?found=$1 [L]

RewriteCond $1 !-f
RewriteRule ^(.*)$ /index.php?notfound=$1 [L]

UPDATE (Example):

/shop/some-user-friendly-alias.999.400x500.jpg 

I rewrite it to REAL path /images/999/400x500.jpg But this image not exists and I want to generate thumbnail on the fly.

Upvotes: 1

Views: 714

Answers (3)

Alexey
Alexey

Reputation: 363

Solved. Sorry for inconvenience caused. Done by two .htaccess files. First - inside root dir: /.htaccess

RewriteEngine on
RewriteCond $1 ^fooimage
RewriteRule ^(fooimage\-(cup|girl|404)\.jpg)$ /realpath/$2.jpg [L]

Second inside realpath: /realpath/.htaccess

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !^generate\.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ generate.php?notfound=$1 [L]

So if real image is not found script will generate it!

Upvotes: 0

anubhava
anubhava

Reputation: 786359

Something like this should work for you:

RewriteEngine On

# images exists in /realpath/
RewriteCond %{DOCUMENT_ROOT}/realpath/$1 -f
RewriteRule ^fakeimages/([^.]+\.[^.]+\.jpg)$ /realpath/$1 [L,NC]

# images doesn't exist in /realpath/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^fakeimages/([^.]+)\.([^.]+)\.jpg$ /generator.php?name=$1&size=$2 [L,NC,QSA]

Upvotes: 1

Reeno
Reeno

Reputation: 5705

The following is a script I use. You may adapt it to your needs.

Put a .htaccess in / with the following code

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^imgresize/(.+)$ imgresize/imgresize.php

The following code is in /imgresize/imgresize.php

<?php
// no image requested
if(!isset($_SERVER['REQUEST_URI']) || empty($_SERVER['REQUEST_URI'])) {
    header('HTTP/1.0 404 Not Found');
    exit;
}
// thumbnail already exists (should never be called as the .htaccess is handling this)
if(file_exists('../'.$_SERVER['REQUEST_URI'])) {
    header('Content-type: image'); 
    readfile('../'.$_SERVER['REQUEST_URI']);
    exit;
}

// extract new width, new height and filename from request
preg_match_all('%/imgresize/([0-9]+)x([0-9]+)/(.+)$%isU', $_SERVER['REQUEST_URI'], $matches);
$new_width = $matches[1][0];
$new_height = $matches[2][0];
$filename = $matches[3][0];
// file doesn't exist
if(!file_exists('../'.$filename)) {
    header('HTTP/1.0 404 Not Found');
    exit;
}

// get width, height and file format from the original image
list($ori_width, $ori_height, $type, $attr) = getimagesize('../'.$filename);

// create new image
if($type == IMAGETYPE_JPEG) {
    $ori_image = imagecreatefromjpeg('../'.$filename);
}
elseif( $type == IMAGETYPE_GIF ) {
    $ori_image = imagecreatefromgif('../'.$filename);
}
elseif( $type == IMAGETYPE_PNG ) {
    $ori_image = imagecreatefrompng('../'.$filename);
}

// calculate new image ratio
$src_x = $src_y = 0;
if($ori_height/$new_height > $ori_width/$new_width) {
    $old_height = $ori_height;
    $ori_height = $ori_width/($new_width/$new_height);
    $src_y = $old_height/2 - $ori_height/2;
}
else {
    $old_width = $ori_width;
    $ori_width = $ori_height/($new_height/$new_width);
    $src_x = $old_width/2 - $ori_width/2;
}

// resize original image
$new_image = imagecreatetruecolor($new_width, $new_height);
imagecopyresampled($new_image, $ori_image, 0, 0, $src_x, $src_y, $new_width, $new_height, $ori_width, $ori_height);

// create path
$new = $new_width.'x'.$new_height.'/'.$filename;
$parts = explode('/', $new);
$path = '';
for($i=0;$i<sizeof($parts)-1;$i++) {
    $path .= $parts[$i].'/';
    if(!file_exists($parts[$i])) {
        mkdir($path);
    }
}

// save the created image
imagejpeg($new_image, $new, 90);

// sent the created image to the user
header('Content-Type: image');
imagejpeg($new_image, null, 90);
?>

Now change image paths from e.g. /images/frontpage/head.jpg to /imgresize/300x500/images/frontpage/head.jpg (300=width, 500=height). If the image is already resized, the PHP script won't be called at all (the RewriteCond %{REQUEST_FILENAME} !-f in the .htaccess), only the image is served to the user. If the resized image doesn't exist, it will be created, saved as /imgresize/300x500/images/frontpage/head.jpg (so the virtual path from the first request will become the real path for all following requests) and sent to the user.

Upvotes: 2

Related Questions