35

I do fetch a file with

$fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
$str = stream_get_contents($fp);
fclose($fp);

and then the method gives it back as image. But when fopen() fails, because the file did not exists, it throws an error:

[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...

This is coming back as json, obviously.

The Question is now: How can i catch the error and prevent the method from throwing this error directly to the client?

Fabian
  • 1,806
  • 5
  • 25
  • 40
  • 1
    i tried something like this `if($fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb")){ throw this->createNotFoundException('No image found for id '.$team_id); }` but it didnt worked. – Fabian Jul 15 '14 at 08:54
  • i did also tried try catch block, but didnt worked. the error was readable to the client. – Fabian Jul 15 '14 at 08:56
  • `try { $fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb"); } catch(Exception $e) { throw $this->createNotFoundException('No image found for id '.$team_id); }` – Fabian Jul 15 '14 at 08:58

4 Answers4

61

You should first test the existence of a file by file_exists().

try
{
  $fileName = 'uploads/Team/img/'.$team_id.'.png';

  if ( !file_exists($fileName) ) {
    throw new Exception('File not found.');
  }

  $fp = fopen($fileName, "rb");
  if ( !$fp ) {
    throw new Exception('File open failed.');
  }  
  $str = stream_get_contents($fp);
  fclose($fp);

  // send success JSON

} catch ( Exception $e ) {
  // send error message if you can
} 

or simple solution without exceptions:

$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ) {

  $str = stream_get_contents($fp);
  fclose($fp);

  // send success JSON    
}
else
{
  // send error message if you can  
}
Giacomo1968
  • 25,759
  • 11
  • 71
  • 103
Cendak
  • 1,022
  • 9
  • 8
  • 2
    FWIW This can still throw OP's original warning if by chance `$fileName` is deleted in the nanosecond between `fopen`. Which is predominantly reproducible on high-traffic sites. Probably the only scenario where I'd be ok with silencing anything: `$fp = @fopen(....); if (!$fp) throw....` – zanderwar Jun 17 '21 at 03:16
  • Also, `file_exists` is not usable when using non-file resources. If all is required is hiding the error, prefixing `fopen` with `@` (`@fopen`) already helps, but it does not give you the error. – Simao Gomes Viana Apr 24 '23 at 12:27
4

You can use the file_exists() function before calling fopen().

if(file_exists('uploads/Team/img/'.$team_id.'.png')
{
    $fp = fopen('uploads/Team/img/'.$team_id.'.png', "rb");
    $str = stream_get_contents($fp);
    fclose($fp);
}
Refazul
  • 119
  • 1
  • 5
1

Generically - This is probably the best way to do file-io in php (as mentioned by @Cendak here)

$fileName = 'uploads/Team/img/'.$team_id.'.png';
if ( file_exists($fileName) && ($fp = fopen($fileName, "rb"))!==false ){
    $str = stream_get_contents($fp);
    fclose($fp);
    // send success JSON    
}else{
    // send an error message if you can  
}

But it does not work with PHP 7.3, these modifications do,

if(file_exists($filename) && ($fp = fopen($filename,"r") !== false)){
        $fp = fopen($filename,"r");
        $filedata = fread($fp,filesize($filename));
        fclose($fp);
}else{
        $filedata = "default-string";
}
Sat93
  • 111
  • 1
  • 4
0
[{"message":"Warning: fopen(uploads\/Team\/img\/1.png): failed to open stream: No such file or directory in C:\...

the error is clear: you've put the wrong directory, you can try what you whant but it'll not work. you can make it work with this:

  1. take your file and put it in the same folder of your php file (you'll be able to move it after don't worry, it's about your error) or on a folder "higher" of your script (just not outside of your www folder)
  2. change the fopen to ('./$team_id.'png',"rb");
  3. rerun your script file

don't forget this : you can't access a file that is'nt in your "www" folder (he doesn't found your file because he give you her name: the name come from the $team_id variable)

yyg
  • 50
  • 1
  • 11