I have web application in PHP using apache server, linux. For some security reason i am keeping the documents and images outside web root. How can i show these images, when the user login.
4 Answers
PHP by default can already access files outside the web root, unless restricted with an open_basedir directive (or safe mode, but hope you're not in that cage). 
It's normally a good practice to insert within a VirtualHost configuration an open_basedir restriction. You can specify multiple directories separated by : on Linux and ; on windows.
php_admin_value open_basedir /var/www/s/stage:/usr/share/php:/your/dir
To access those files either use an absolute path or a path relative to the position of the PHP file called. (So you'll have to ../ to reach levels above).
Also be sure that directories in which you want to write to are assigned to the webserver user and have write permission.
Otherwise you have second option:
Inside your www directory, create a "image.php" file, with a similar content to:
<?php
  header('Content-Type: image/png');
  readfile("../img/" . $_GET['img']);
?>
And call your images with
<img src="image.php?img=myimage.png" />
Please be aware that your PHP file shouldn't be that simple :) As you may want to address multiple image formats (and providing the correct header for them), checking for malicious file path/inclusions (you don't want to use $_GET without validating/sanitizing the input), extra caching etc. etc. etc.
But this should give you an idea on how you can target your issue.
- 7,472
 - 2
 - 41
 - 70
 
- 
                    4[Looks familiar.](https://stackoverflow.com/questions/13357994/access-a-file-which-is-located-before-outside-the-server-root-directory#answer-13358201) – showdev Sep 06 '17 at 20:57
 - 
                    It is possible, but its not the same answer. – Legionar Sep 07 '17 at 08:52
 - 
                    I went with something like this to prevent cached images. $r = rand(1,9999); print '
'; – drooh Jan 11 '21 at 19:52
 
For my application, none of those answers were working - I simply couldn't get the image to display and it wasn't really feasible for me to add a new php file to call because reasons. What DID work for me is
$filename = read_filename_from_database;
$fileDir = "/path/to/files/";
$file = $fileDir . $filename;
if (file_exists($file))
{
     $b64image = base64_encode(file_get_contents($file));
     echo "<img src = 'data:image/png;base64,$b64image'>";
}
- 1,482
 - 1
 - 14
 - 23
 
As simple as that, this will output the image with correct headers,
remember that you have to set the header() before flushing anything out of the output buffer
=> no echo or print before
$file = '../../somedirectory/image.jpg';
header('Content-Type:image/jpeg');
header('Content-Length: '.filesize($file));
echo file_get_contents($file);
- 431
 - 4
 - 12
 
- 653
 - 4
 - 14
 
use the ob_clean() function of php before the readfile()
it will usefull to avoid space like issues
- 686
 - 1
 - 9
 - 20