Pawel Urban Pawel Urban - 1 month ago 10
Apache Configuration Question

.htaccess - image filed treated as PHP file

I wrote a simple PHP REST application and I have a problem with serving static files. My directory structure looks as follows :


  • public


    • content (here are static files)

    • index.php


  • src (my application sources)

  • vendor (Composer dependencies)



I have two .htaccess files in my project - in root directory and in public directory :

root .htaccess

RewriteEngine on
RewriteRule ^$ public/ [L]
RewriteRule (.*) public/$1 [L]


public .htaccess (standard Slim template)

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA]


These configuration looks like that because I wanted all requests to be redirected to public directory and omit that part in request uri to have http://host.com/rest/XXX instead http://host.com/rest/public/XXX.

Right now I can't access files using http://host.com/rest/content/file-test.ext - it seems like it's treated as PHP file because I getting error :

Warning: Unexpected character in input: '' (ASCII=30) state=0 in /rest/public/content/file-test.ext on line 298

Parse error: syntax error, unexpected '@' in /rest/public/content/file-test.ext on line 298


I already tried to put separate .htaccess file inside content directory with
RewriteEngine off
or
php_flags engine off
.

I can't change any webserver configuration because hosting is provided by 3rd part person I can't even request any changes. host.com/rest i set to my document root and when I connect via FTP I can't go upwards from that directory so solutions regarding webserver configuration changes are not correct in my case.

Please help me to get static files working !

Answer

Utilize Slim: it retains control in your hands and you don't solve the problem with .htaccess.

Also:

  • you can change the route or containing folder anytime you wish.
  • you can set additional headers e.g. for caching.
$app->get('/content/{pathToImage}', function($request, $response, $args) {
    $pathToFile = $args['pathToImage'];
    $containingFolder = '../content/'; // the actual folder where files are stored
    // if you want to omit file extension in the url, we'll have to find it out
    $matches = glob($containingFolder.$fileName.'.*');
    if ($matches) {
        $clientImagePath = array_shift($matches); // let's grab the first file matching our mask
        $clientImage = @file_get_contents($clientImagePath);
        $finfo = new \Finfo(FILEINFO_MIME_TYPE);
        $response->write($clientImage);
        return $response->withHeader('Content-Type', $finfo->buffer($clientImage));
    } else {
        // if no matches found, throw exception that will be handled by Slim
        throw new \Slim\Exception\NotFoundException($request, $response);
    }
});

In case URLs like content/image.png (having file extension) is acceptable for you, you can do this in a simpler way:

$app->get('/assets/images/{pathToImage}', function($request, $response, $args) {
    $pathToFile = $args['pathToImage'];
    $path = '../content/'.$fileName;
    $image = @file_get_contents($path);
    $finfo = new \Finfo(FILEINFO_MIME_TYPE);
    $response->write($image);
    return $response->withHeader('Content-Type', $finfo->buffer($image));
});
Comments