file_exists() returns false, but the file DOES exist
I’m having a very weird issue with file_exists(). I’m using this function to check if 2 different files in the same folders do exist. I’ve double-checked, they BOTH do exist.
echo $relative . $url['path'] . '/' . $path['filename'] . '.jpg'; Result: ../../images/example/001-001.jpg echo $relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension']; Result: ../../images/example/001-001.PNG
var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.jpg')); Result: bool(false) var_dump(file_exists($relative . $url['path'] . '/' . $path['filename'] . '.' . $path['extension'])); Result: bool(true)
I don’t get it — both of these files do exist. I’m running Windows, so it’s not related to a case-sensitive issue. Safe Mode is off. What might be worth mentioning though is that the .png one is uploaded by a user via FTP, while the .jpg one is created using a script. But as far as I know, that shouldn’t make a difference. Any tips? Thanks
For me it ended up being because it requires an absolute path, not a relative path. Some PHP functions accept a path relative to the current file, one being parse_ini_file.
I also thought I had this issue. After checking the spelling 10 times I realised that the filename ended in «.jpg.jpg». It’s true, I am a failure
15 Answers 15
file_exists() just doesn’t work with HTTP addresses.
It only supports filesystem paths (and FTP, if you’re using PHP5.)
if (file_exists($_SERVER['DOCUMENT_ROOT']."/folder/test.txt") echo "file exists";
if (file_exists("www.mysite.com/folder/test.txt") echo "file exists";
Results of the file_exists() are cached, so try using clearstatcache() . If that not helped, recheck names — they might be similar, but not same.
This was indeed the problem. It seemed the script replaced _’s with -‘s. Very hard to miss (and annoying) 😐
For me clearstatcache() — didn’t helped but. My class name was Multimedia. Then i used clearstatcache() — still didn’t work. Then i renamed file to Multimedia2 didn’t helped to. That was strange. Then I renamed file to Abc. It worked. Then renamed to Multimedia and it worked again 😀 It took me about half an hour.
I also had problem with these. because i supplied file_exists() a full path. it shouldn’t be a full path. for example www.abc.com/photo.jpg, you should supply only photo.jpg not with domain.
clearstatcache() is not usefull here : according to the doc, PHP doesn’t cache information about non existent files. So if file_exists returns false instead of true, file status cache has nothing to do with it. If, on the other hand, file_exists returns true intsead of false, clearstatecache might be a solution. @see php.net/manual/en/function.clearstatcache.php
I found that what works for me to check if a file exists (relative to the current php file it is being executed from) is this piece of code:
$filename = 'myfile.jpg'; $file_path_and_name = dirname(__FILE__) . DIRECTORY_SEPARATOR . ""; if ( file_exists($file_path_and_name) ) < // file exists. Do some magic. >else < // file does not exists. >
dirname(FILE) — saved me as path was wrong in docker container where script was running, thank you!
Just my $.02: I just had this problem and it was due to a space at the end of the file name. It’s not always a path problem — although that is the first thing I check — always. I could cut and paste the file name into a shell window using the ls -l command and of course that locates the file because the command line will ignore the space where as file_exists does not. Very frustrating indeed and nearly impossible to locate were it not for StackOverflow.
HINT: When outputting debug statements enclose values with delimiters () or [] and that will show a space pretty clearly. And always remember to trim your input.
It’s because of safe mode. You can turn it off or include the directory in safe_mode_include_dir . Or change file ownership / permissions for those files.
Safe mode is already turned off, so that’s not the issue. Also, the permissions should be file-specific, as they’re both in the same folder. I’ve never had these issues in Windows, but when looking at the permissions, I don’t see any difference between the two.
Ah, sorry didn’t see safe mode is off. If permissions are the same, you might need to check the owner id or the group id for those files, it could be that your webuser doesn’t belong to the group or is not the owner of the file.
Try using DIRECTORY_SEPARATOR instead of ‘/’ as separator. Windows uses a different separator for file system paths (backslash) than Linux and Unix systems.
A very simple trick is here that worked for me.
When I write following line, than it returns false.
if(file_exists('/my-dreams-files/'.$_GET['article'].'.html'))
And when I write with removing URL starting slash, then it returns true.
if(file_exists('my-dreams-files/'.$_GET['article'].'.html'))
This seems to be expected, provided that my-dreams-files is not in the root of the drive. / with nothing in front of it is the root. Your second example is relative.
I also had a slash because I assumed the slash would navigate to the root of the website, but it don’t :/
I have a new reason this happens — I am using PHP inside a Docker container with a mounted volume for the codebase which resides on my local host machine.
I was getting file_exists == FALSE (inside Composer autoload ), but if I copied the filepath into terminal — it did exist! I tried the clearstatche() , checked safe-mode was OFF.
Then I remembered the Docker volume mapping: the absolute path on my local host machine certainly doesn’t exist inside the Docker container — which is PHP’s perspective on the world.
(I keep forgetting I’m using Docker, because I’ve made shell functions which wrap the docker run commands so nicely. )
I would like to upvote this 1000 times! I spent hours thinking it was a permissions issue but all I needed to do was remap my PHP script from /Volumes/MyDrive to /var/www/html. Thanks for the reminder
I have the same problem. Not being a Docker expert, I am not sure how to remap. When I try $iRc=file_exists(«/opt/docker-substantiator/app/assets/image_crud/views/list.php»);, which is the full path on the host, it fails. Of course on the cmd line ls /opt/docker-substantiator/app/assets/image_crud/views/list.php works fine. What should the path be to list.php in my container?
@RichardBernstein it depends how you mounted the volume. You just have to make sure your app is using a path which is according to the container’s filesystem, not the host’s. I would jump inside it to check it’s right using docker exec -it container-name bash then poke around until you understand the inner filesystem. You can figure it out from the volume mapping (e.g. -v /Volumes/MyDrive:/var/www/html) but seeing it place makes it clearer.
@RichardBernstein but if your path /opt/docker-substantiator/app/assets/image_crud/views/list.php is correct within the container (i.e. it’s not a path on your host / your dev machine), then you have may a different problem.
Thanks scipilot. I think that the issue is the mapping as you state. I loaded up bash and I see :/app#. I guess I need to learn the commands to see the inner filesystem. I didnt create the original containers so I don’t know where the docker run got its mount instructs from. Thx again.
It can also be a permission problem on one of the parent folders or the file itself.
Try to open a session as the user running your webserver and cd into it. The folder must be accessible by this user and the file must be readable.
If not, php will return that the file doesn’t exist.
have you tried manual entry. also your two extensions seem to be in different case
var_dump(file_exists('../../images/example/001-001.jpg')); var_dump(file_exists('../../images/example/001-001.PNG'));
A custom_file_exists() function inspired by @Timur, @Brian, @Doug and @Shahar previous answers:
function custom_file_exists($file_path='')< $file_exists=false; //clear cached results //clearstatcache(); //trim path $file_dir=trim(dirname($file_path)); //normalize path separator $file_dir=str_replace('/',DIRECTORY_SEPARATOR,$file_dir).DIRECTORY_SEPARATOR; //trim file name $file_name=trim(basename($file_path)); //rebuild path $file_path=$file_dir.""; //If you simply want to check that some file (not directory) exists, //and concerned about performance, try is_file() instead. //It seems like is_file() is almost 2x faster when a file exists //and about the same when it doesn't. $file_exists=is_file($file_path); //$file_exists=file_exists($file_path); return $file_exists; >
This answer may be a bit hacky, but its been working for me —
$file = 'path/to/file.jpg'; $file = $_SERVER['REQUEST_SCHEME'].'://'.$_SERVER['HTTP_HOST'].'/'.$file; $file_headers = @get_headers($file); if($file_headers[0] == 'HTTP/1.1 404 Not Found') < $exists = false; >else
apparently $_SERVER[‘REQUEST_SCHEME’] is a bit dicey to use with IIS 7.0 + PHP 5.3 so you could probably look for a better way to add in the protocol.
I spent the last two hours wondering what was wrong with my if statement: file_exists($file) was returning false, however I could call include($file) with no problem.
It turns out that I didn’t realize that the php include_path value I had set in the .htaccess file didn’t carry over to file_exists , is_file , etc.
//does work, file_exists returns true if ( file_exists('/home/user/public_html/includes/config.php') ) < include('includes/config.php'); >?>
Just goes to show that «shortcuts for simplicity» like setting the include_path in .htaccess can just cause more grief in the long run.
In my case, the problem was a misconception of how file_exists() behaves with symbolic links and .. («dotdot» or double period) parent dir references. In that regard, it differs from functions like require , include or even mkdir() .
Given this directory structure:
/home/me/work/example/ www/ /var/www/example.local/ tmp/ public_html -> /home/me/work/example/www/
file_exists(‘/var/www/example.local/public_html/../tmp/’); would return FALSE even though the subdir exists as we see, because the function traversed up into /home/me/work/example/ which does not have that subdir.
For this reason, I have created this function:
/** * Resolve any ".." ("dotdots" or double periods) in a given path. * * This is especially useful for avoiding the confusing behavior `file_exists()` * shows with symbolic links. * * @param string $path * * @return string */ function resolve_dotdots( string $path ) < if (empty($path)) < return $path; >$source = array_reverse(explode(DIRECTORY_SEPARATOR, $path)); $balance = 0; $parts = array(); // going backwards through the path, keep track of the dotdots and "work // them off" by skipping a part. Only take over the respective part if the // balance is at zero. foreach ($source as $part) < if ($part === '..') < $balance++; >else if ($balance > 0) < $balance--; >else < array_push($parts, $part); >> // special case: path begins with too many dotdots, references "outside // knowledge". if ($balance > 0) < for ($i = 0; $i < $balance; $i++) < array_push($parts, '..'); >> $parts = array_reverse($parts); return implode(DIRECTORY_SEPARATOR, $parts); >
PHP file_exists() returning false on some files
I’m having a strange problem with the file_exists() PHP function on a Linux server. When using file_exists to check the image is on the server before editing it, it will sometimes fail for no apparent reason. File paths are absolute and I’ve checked them through ssh they are 100% at the specified path. The images that fail file_exists() will still display in the browser. The code doesn’t make a difference a basic var_dump(file_exists(‘/home/user/path/image.jpg’)); will return false. The file permissions/ownerships are exactly the same on all images and parent directories. Safe mode is off. There are no PHP errors. I’m stumped now and not sure what to look for. Here is how the images are on the server:
/home/user/public_html/images/location/1.jpg -- will work /home/user/public_html/images/location2/1.jpg -- won't work /home/user/public_html/images/location2/2.jpg -- will work
- Yes the images are there, it’s definitely not caching.
- Safe mode is off (I already mentioned this in my post).
- Paths are not symlinks but direct links to the files location on the server.
- Phoenix, it is consistent. The working files will always work and vice versa. The names are 1.jpg, 1.thumb.jpg, etc. so it’s not a problem with strange characters or spaces.
[root@server ~]# ls -l /home/user/public_html/images/Hawkhurst/ total 92 -rwxr-xr-x 1 user user 24501 Aug 11 2009 1.jpg -rwxr-xr-x 1 user user 1672 Aug 11 2009 1.thumb.jpg -rwxr-xr-x 1 user user 14983 Aug 11 2009 2.jpg -rwxr-xr-x 1 user user 1370 Aug 11 2009 2.thumb.jpg -rwxr-xr-x 1 user user 17238 Aug 11 2009 3.jpg -rwxr-xr-x 1 user user 1453 Aug 11 2009 3.thumb.jpg -rwxr-xr-x 1 user user 14168 Aug 11 2009 4.jpg -rwxr-xr-x 1 user user 1464 Aug 11 2009 4.thumb.jpg [root@server ~]#
I have tried with permissions 777 and 755 which make no difference. For example in this folder, 1 and 2 may work whilst 3 & 4 don’t.
I ran a quick test to see what apache/php runs as and they do run as nobody, but this does not explain why some images work and some don’t with the exact same permissions.
EDIT 2: Problem solved. Can’t believe how stupid it was, some of the filenames which were called from a database had spaces at the end. Whoever made the original script didn’t run any sort of cleaning up before saving them.