fopen

(PHP 4, PHP 5)

fopenÖffnet eine Datei oder URL

Beschreibung

resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )

fopen() bindet eine benannte Ressource, die durch filename spezifiziert wurde, an einen Stream.

Parameter-Liste

filename

Hat filename die Form "schema://..." wird angenommen, dass es sich hier um einen URL handelt und PHP sucht nach einem Protokollhandler (auch als Wrapper bekannt) für dieses Schema. Sind keine Wrapper für dieses Protokoll registriert, gibt PHP als Hilfe zum Verfolgen potentieller Probleme in Ihrem Skript einen Hinweis aus und setzt dann weiter fort, als wenn filename eine reguläre Datei spezifiziert.

Ist PHP zu dem Schluss gekommen, dass filename eine lokale Datei spezifiziert, wird es versuchen, einen Stream an dieser Datei zu öffnen. Die Datei muss für PHP zugreifbar sein, weshalb Sie sicherstellen müssen, dass die Dateirechte diesen Zugriff ermöglichen. Wenn Sie Safe Mode oder open_basedir aktiviert haben, können weitere Einschränkungen zutreffen.

Kam PHP zum Schluss, dass es sich bei filename um ein registriertes Protokoll handelt, und ist dieses Protokoll als ein Netzwerk URL registriert, prüft PHP, ob allow_url_fopen aktiviert ist. Ist es nicht aktiviert, gibt PHP eine Warnung aus, und der Aufruf von fopen wird scheitern.

Hinweis:

Die Liste der unterstützten Protokolle können Sie unter Unterstützte Protokolle and Wrappers finden. Einige Protokolle (auch als Wrapper bezeichnet) unterstützen context und/oder php.ini Optionen. Beziehen sie sich auf die jeweilige Seite für das genutzte Potokoll, um eine Liste der Optionen, die gesetzt werden können, zu erhalten. (z.B. php.ini Wert user_agent genutzt vom http Wrapper).

Achten sie darauf, unter Windows alle Backslash-Zeichen, die in Pfaden genutzt werden, zu maskieren oder nutzen sie Schrägstriche (Slash).

<?php
$handle 
fopen("c:\\verzeichnis\\ressource.txt""r");
?>

mode

Der mode Parameter spezifiziert den Zugriffstyp, den sie auf den Stream anfordern. Es kann einer der folgenden sein:

Eine Liste der möglichen Modi von fopen() mittels mode
mode Beschreibung
'r' Nur zum Lesen geöffnet; platziere Dateizeiger auf Dateianfang.
'r+' Zum Lesen und Schreiben geöffnet; platziere Dateizeiger auf Dateianfang.
'w' Nur zum Schreiben geöffnet; platziere Dateizeiger auf Dateianfang und kürze die Datei auf eine Länge von 0. Existiert die Datei nicht, versuche, diese zu erzeugen.
'w+' Zum Schreiben und Lesen geöffnet; platziere Dateizeiger auf Dateianfang und kürze die Datei auf eine Länge von 0. Existiert die Datei nicht, versuche, diese zu erzeugen.
'a' Nur zum Schreiben geöffnet; platziere Dateizeiger auf Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen.
'a+' Zum Schreiben und Lesen geöffnet; platziere Dateizeiger auf Dateiende. Existiert die Datei nicht, versuche, diese zu erzeugen.
'x' Erzeuge und Öffne nur zum Schreiben; platziere Dateizeiger auf Dateianfang. Falls die Datei schon existiert, wird der fopen() Aufruf fehlschlagen durch Rückgabe von FALSE und dem Auslösen eines Fehlers der Stufe E_WARNING. Existiert die Datei nicht, versuche, diese zu erzeugen. Dies ist zur Angabe der O_EXCL|O_CREAT Flags für den darunterliegenden open(2) System Aufruf äquivalent.
'x+' Erzeuge und Öffne zum Schreiben und Lesen; ansonsten ist das Verhalten gleich wie bei 'x'.
'c' Öffne Datei nur zum Schreiben. Wenn die Datei nicht existiert, wird diese erzeugt. Wenn sie existiert, wird sie weder gekürzt (im Gegensatz zu 'w'), noch schlägt der Aufruf dieser Funktion fehl (wie dies mit 'x' der Fall ist). Der Dateizeiger wird auf den Dateianfang platziert. Dies kann nützlich sein, wenn man eine "beratende" (kooperative) Sperre erhalten möchte (siehe flock()) bevor man versucht, die Datei zu ändern, da die Nutzung von 'w' die Datei kürzen könnte, bevor die Sperre erhalten wurde (falls Kürzen gewünscht ist, kann ftruncate() genutzt werden, nachdem die Sperre angefragt wurde).
'c+' Öffne Datei zum Lesen und Schreiben; ansonsten ist das Verhalten gleich wie bei 'c'.

Hinweis:

Verschiedene Betriebssysteme haben unterschiedliche Zeilenende Konventionen. Wenn sie eine Text Datei schreiben und einen Zeilenumbruch einfügen möchten, müssen sie das/die korrekte(n) Zeilenende Zeichen für ihr Betriebssystem nutzen. Unix basierte Systeme nutzen \n als Zeilenende Zeichen, Windows basierte Systeme nutzen \r\n als Zeilenende Zeichen und Macintosh basierte Systeme nutzen \r als Zeilenende Zeichen.

Wenn sie die falschen Zeilenende Zeichen beim Schreiben ihrer Dateien nutzen, kann es sein, dass andere Anwendungen, die diese Dateien öffnen, "seltsam aussehen".

Windows bietet einen Text-Mode translations Flag ('t') an, der transparent \n zu \r\n übersetzt, wenn mit der Datei gearbeitet wird. Andererseits können sie auch 'b' nutzen, um Binärmode zu erzwingen, der ihre Daten nicht übersetzt. Um diese Flags zu nutzen, geben sie entweder 'b' oder 't' als das letzte Zeichen des mode Parameters an.

Der Standard Übersetzungsmodus hängt von der SAPI und der PHP Version ab, die sie nutzen, daher ist es empfehlenswert, immer den passenden Flag aus Portabilitätsgründen anzugeben. Sie sollten 't' Modus nutzen, wenn sie mit Textdateien arbeiten und sie nutzen \n um die Zeilenenden im Skript zu begrenzen, erwarten aber, dass ihre Dateien mit Anwendungen wie etwa Notepad lesbar sind. Ansonsten sollten sie 'b' nutzen.

Wenn sie beim Arbeiten mit binären Dateien nicht das 'b' Flag angeben, können sie seltsame Probleme mit ihren Daten erleben, einschließlich zerstörter Bild Dateien und merkwürdiger Probleme mit \r\n Zeichen.

Hinweis:

Aus Portabilitätsgründen wird dringend empfohlen, dass sie immer das 'b' Flag nutzen, wenn sie Dateien mit fopen() öffnen.

Hinweis:

Außerdem wird aus Gründen der Portabilität dringend empfohlen, dass sie Code umschreiben, der den 't' Modus nutzt oder sich darauf verlässt, so dass die korrekten Zeilenendungen und der 'b' Modus stattdessen genutzt werden.

use_include_path

Der optionale dritte Parameter use_include_path kann auf '1' oder TRUE gesetzt werden, wenn sie wollen, dass nach der Datei auch im include_path gesucht wird.

context

Hinweis: Die Kontext-Unterstützung gibt es seit PHP 5.0.0. Eine Beschreibung von Kontexten finden Sie unter Streams.

Rückgabewerte

Gibt bei Erfolg eine Dateizeiger Ressource zurück oder FALSE bei Fehlern.

Fehler/Exceptions

Wenn das Öffnen fehlschlägt, wird ein Fehler der Stufe E_WARNING erzeugt. Sie können @ um diese Warnung zu unterdrücken.

Changelog

Version Beschreibung
4.3.2 Seit PHP 4.3.2 ist der Standard Modus auf binär für alle Plattformen, die zwischen binärem und Text Modus unterscheiden, gesetzt. Wenn sie Probleme mit ihren Skripten nach einem Upgrade haben, versuchen sie als Übergangslösung das 't' Flag zu nutzen bis sie ihr Skript wie zuvor beschrieben portabler umgeschrieben haben.
4.3.2 Die 'x' und 'x+' Optionen wurden hinzugefügt.
5.2.6 Die 'c' und 'c+' Optionen wurden hinzugefügt.

Beispiele

Beispiel #1 fopen() Beispiele

<?php
$handle 
fopen("/home/rasmus/file.txt""r");
$handle fopen("/home/rasmus/file.gif""wb");
$handle fopen("http://www.example.com/""r");
$handle fopen("ftp://user:password@example.com/somefile.txt""w");
?>

Anmerkungen

Warnung

Bei SSL-Verbindungen zusammen mit Microsoft IIS hält sich dieser Webserver nicht an das Protokoll und schließt die Verbindung ohne ein close_notify zu senden. PHP quittiert dieses Fehlverhalten mit "SSL: Fatal Protocol Error", wenn das Ende der Daten erreicht ist. Eine mögliche Lösung besteht darin, den Level von error_reporting herabzusetzten und Warnings auszuschließen. Ab PHP 4.3.7 kann PHP fehlerhafte IIS-Serversoftware erkennen, wenn Sie einen Stream mit dem https://-Wrapper öffnen, und unterdrückt die Warnung für Sie. Falls Sie fsockopen() benutzen, um einen ssl://-Socket zu öffnen, müssen Sie selbst dafür Sorge tragen, die Warnung zu erkennen und diese zu unterdrücken.

Hinweis: Wenn Safe Mode aktiviert ist überprüft PHP, ob das Arbeitsverzeichnis, die gleiche UID (Eigentümer) hat wie das Skript selbst.

Wenn sie Probleme beim Lesen und Schrieben von Dateien haben und sie nutzen die Server Modul Version von PHP, denken sie daran, sicherzustellen, dass die Dateien und Verzeichnisse, die sie nutzen, für den Server Prozess zugänglich sind.

Siehe auch

add a note add a note

User Contributed Notes 48 notes

up
18
chapman at worldtakeoverindustries dot com
2 years ago
Note - using fopen in 'w' mode will NOT update the modification time (filemtime) of a file like you may expect. You may want to issue a touch() after writing and closing the file which update its modification time. This may become critical in a caching situation, if you intend to keep your hair.
up
6
php at delhelsa dot com
6 years ago
With php 5.2.5 on Apache 2.2.4, accessing files on an ftp server with fopen() or readfile() requires an extra forwardslash if an absolute path is needed.

i.e., if a file called bullbes.txt is stored under /var/school/ on ftp server example.com and you're trying to access it with user blossom and password buttercup, the url would be:

ftp://blossom:buttercup@example.com//var/school/bubbles.txt

Note the two forwardslashes. It looks like the second one is needed so the server won't interpret the path as relative to blossom's home on townsville.
up
4
gmdebby at gmail dot com
5 years ago
I was wondering why was added the "x" mode, it works only if the file do not exists, will create it and open it in read only, it's useless !!
But I found something I could do with that.

Here is a little mk_file function.

<?php
function mk_file($filename) {
    if(!
is_file($filename)) {
       
fclose(fopen($filename,"x")); //create the file and close it
       
return true;
    } else return
false; //file already exists
}
?>

You can improve it, add chmod support etc...
up
4
Jem Tallon
10 years ago
If you're using fopen to open a URL that requires authorization, you might need to force a HTTP/1.0 request for it since fopen won't support HTTP/1.1 requests. You can do that by setting your user_agent to one that is known only to support HTTP/1.0 (most webservers will be configured to force HTTP/1.0 for some browsers). Here's what worked for me:

<?php
$returned
=URLopen("http://$username:$password@example.com");

function
URLopen($url)
{
       
// Fake the browser type
       
ini_set('user_agent','MSIE 4\.0b2;');

       
$dh = fopen("$url",'r');
       
$result = fread($dh,8192);                                                                                                                            
        return
$result;
}
?>
up
2
simon dot riget at gamil dot com
1 year ago
Writing and reading on a serial port.

If you are unable or unwilling to install the serial device library for PHP, its still possible to communicate through a serial port or USB device.

There are two issues to note:
- you must use a system call to set the port control options
- you must use NON blocking stream mode for reading (not for writing unless you use flow control)

<?php
// Set timeout to 500 ms
$timeout=microtime(true)+0.5;

// Set device controle options (See man page for stty)
exec("/bin/stty -F /dev/ttyS0 19200 sane raw cs8 hupcl cread clocal -echo -onlcr ");
   
// Open serial port
$fp=fopen("/dev/ttyS0","c+");
if(!
$fp) die("Can't open device");

// Set blocking mode for writing
stream_set_blocking($fp,1);
fwrite($fp,"foo\n");

// Set non blocking mode for reading
stream_set_blocking($fp,0);
do{
 
// Try to read one character from the device
 
$c=fgetc($fp);

 
// Wait for data to arive
 
if($c === false){
     
usleep(50000);
      continue;
  } 
 
 
$line.=$c;
   
}while(
$c!="\n" && microtime(true)<$timeout);
 
echo
"Responce: $line"
?>
up
4
flobee
8 years ago
download: i need a function to simulate a "wget url" and do not buffer the data in the memory to avoid thouse problems on large files:
<?php
function download($file_source, $file_target) {
       
$rh = fopen($file_source, 'rb');
       
$wh = fopen($file_target, 'wb');
        if (
$rh===false || $wh===false) {
// error reading or opening file
          
return true;
        }
        while (!
feof($rh)) {
            if (
fwrite($wh, fread($rh, 1024)) === FALSE) {
                  
// 'Download error: Cannot write to file ('.$file_target.')';
                  
return true;
               }
        }
       
fclose($rh);
       
fclose($wh);
       
// No error
       
return false;
    }
?>
up
2
splogamurugan at gmail dot com
3 years ago
While opening a file with multibyte data (Ex: données multi-octets), faced some issues with the encoding. Got to know that it uses  windows-1250. Used iconv to convert it to UTF-8 and it resolved the issue. 

<?php
function utf8_fopen_read($fileName) {
   
$fc = iconv('windows-1250', 'utf-8', file_get_contents($fileName));
   
$handle=fopen("php://memory", "rw");
   
fwrite($handle, $fc);
   
fseek($handle, 0);
    return
$handle;
}
?>

Example usage:

<?php
$fh
= utf8_fopen_read("./tpKpiBundle.csv");
while ((
$data = fgetcsv($fh, 1000, ",")) !== false) {
    foreach (
$data as $value) {
        echo
$value . "<br />\n";
    }
}
?>

Hope it helps.
up
2
Luiz Miguel Axcar (lmaxcar at yahoo dot com dot br)
9 years ago
If you are getting message "Warning: fopen(): URL file-access is disabled in the server configuration", you can use function below to get the content from a local or remote file.

Function uses CURL lib, follow the link to get help: http://www.php.net/curl

<?php
/*
   * @return string
   * @param string $url
   * @desc Return string content from a remote file
   * @author Luiz Miguel Axcar (lmaxcar@yahoo.com.br)
*/

function get_content($url)
{
   
$ch = curl_init();

   
curl_setopt ($ch, CURLOPT_URL, $url);
   
curl_setopt ($ch, CURLOPT_HEADER, 0);

   
ob_start();

   
curl_exec ($ch);
   
curl_close ($ch);
   
$string = ob_get_contents();

   
ob_end_clean();
   
    return
$string;    
}

#usage:
$content = get_content ("http://www.php.net");
var_dump ($content);
?>
up
2
info at b1g dot de
9 years ago
Simple class to fetch a HTTP URL. Supports "Location:"-redirections. Useful for servers with allow_url_fopen=false. Works with SSL-secured hosts.

<?php
#usage:
$r = new HTTPRequest('http://www.example.com');
echo
$r->DownloadToString();

class
HTTPRequest
{
    var
$_fp;        // HTTP socket
   
var $_url;        // full URL
   
var $_host;        // HTTP host
   
var $_protocol;    // protocol (HTTP/HTTPS)
   
var $_uri;        // request URI
   
var $_port;        // port
   
    // scan url
   
function _scan_url()
    {
       
$req = $this->_url;
       
       
$pos = strpos($req, '://');
       
$this->_protocol = strtolower(substr($req, 0, $pos));
       
       
$req = substr($req, $pos+3);
       
$pos = strpos($req, '/');
        if(
$pos === false)
           
$pos = strlen($req);
       
$host = substr($req, 0, $pos);
       
        if(
strpos($host, ':') !== false)
        {
            list(
$this->_host, $this->_port) = explode(':', $host);
        }
        else
        {
           
$this->_host = $host;
           
$this->_port = ($this->_protocol == 'https') ? 443 : 80;
        }
       
       
$this->_uri = substr($req, $pos);
        if(
$this->_uri == '')
           
$this->_uri = '/';
    }
   
   
// constructor
   
function HTTPRequest($url)
    {
       
$this->_url = $url;
       
$this->_scan_url();
    }
   
   
// download URL to string
   
function DownloadToString()
    {
       
$crlf = "\r\n";
       
       
// generate request
       
$req = 'GET ' . $this->_uri . ' HTTP/1.0' . $crlf
           
.    'Host: ' . $this->_host . $crlf
           
.    $crlf;
       
       
// fetch
       
$this->_fp = fsockopen(($this->_protocol == 'https' ? 'ssl://' : '') . $this->_host, $this->_port);
       
fwrite($this->_fp, $req);
        while(
is_resource($this->_fp) && $this->_fp && !feof($this->_fp))
           
$response .= fread($this->_fp, 1024);
       
fclose($this->_fp);
       
       
// split header and body
       
$pos = strpos($response, $crlf . $crlf);
        if(
$pos === false)
            return(
$response);
       
$header = substr($response, 0, $pos);
       
$body = substr($response, $pos + 2 * strlen($crlf));
       
       
// parse headers
       
$headers = array();
       
$lines = explode($crlf, $header);
        foreach(
$lines as $line)
            if((
$pos = strpos($line, ':')) !== false)
               
$headers[strtolower(trim(substr($line, 0, $pos)))] = trim(substr($line, $pos+1));
       
       
// redirection?
       
if(isset($headers['location']))
        {
           
$http = new HTTPRequest($headers['location']);
            return(
$http->DownloadToString($http));
        }
        else
        {
            return(
$body);
        }
    }
}
?>
up
1
anfragen at tsgames dot de
4 years ago
Since the http-wrapper doesn't support stat() and so you can't use file_exists() for url's, you can simply use a function like this:

<?php
function http_file_exists($url)
{
$f=@fopen($url,"r");
if(
$f)
{
fclose($f);
return
true;
}
return
false;
}
?>
up
1
Pastix
4 years ago
If fopen() has been disabled for security reasons, is possible a porting FROM:

<?php
$f
=fopen($file,'rb');
$data='';
while(!
feof($f))
   
$data.=fread($f,$size);
fclose($f);
?>

TO:

<?php
$data
= file_get_contents($file); // (PHP 4 >= 4.3.0, PHP 5)
?>

and also a porting FROM:

<?php
$f
= fopen($file,'wb');
fwrite($f,$content,strlen($content));
fclose($f);
?>

TO:

<?php
$f
=file_put_contents($file, $content); // (PHP 5)
?>

For detail read the php manual.
up
1
apathetic012 at gmail dot com
2 years ago
a variable $http_response_header is available when doing the fopen(). Which contains an array of the response header.
up
0
Antoine
2 months ago
On a Windows webserver, when using fopen with a file path stored in a variable, PHP will return an error if the variable isn't encoded in ASCII, which may be the case if the file file path is retrieved from a database.

Possible workaround :
<?
$encoding
= mb_detect_encoding($filePath);
$filePath = mb_convert_encoding($filePath, "ASCII", $encoding);
$filePath = str_replace("?", "", $filePath);
$filePath = addslashes($filePath);

if(
file_exists($filePath)) {
    echo
"File Found.";
   
$handle       = fopen($filePath, "r");
   
$fileContents = fread($handle, filesize($filePath));
   
fclose($handle);
    if(!empty(
$fileContents)) {
        echo
"<pre>".$fileContents."</pre>";
    }
}
else {
    echo
"File Not Found.";
}
?>
up
0
kasper at webmasteren dot eu
2 years ago
"Do not use the following reserved device names for the name of a file:
CON, PRN, AUX, NUL, COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9, LPT1,
LPT2, LPT3, LPT4, LPT5, LPT6, LPT7, LPT8, and LPT9. Also avoid these names
followed immediately by an extension; for example, NUL.txt is not recommended.
For more information, see Namespaces"
it is a windows limitation.
see:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx
up
0
php at richardneill dot org
3 years ago
fopen() will block if the file to be opened is a fifo. This is true whether it's opened in "r" or "w" mode.  (See man 7 fifo: this is the correct, default behaviour; although Linux supports non-blocking fopen() of a fifo, PHP doesn't).
The consequence of this is that you can't discover whether an initial fifo read/write would block because to do that you need stream_select(), which in turn requires that fopen() has happened!
up
0
owltech at larkandowl dot net
3 years ago
[fopen note]

I have been trying unsuccessfully to upload and read a Mac OS file on a Linux server. Lots of records show up a just one big using only the following:

<?php $fhandle = fopen($file, 'r'); ?>
  or
<?php $fhandle = fopen($file, 'rb'); ?>

It does work, however, this way:

<?php
ini_set
('auto_detect_line_endings', TRUE);
$fhandle = fopen($file, 'r');
?>
up
0
magnetik at magnetik dot org
4 years ago
There IS an option to use fopen with a proxy, it's in $context.
No need to recode everything.
up
0
b dot evieux at gmail dot com
4 years ago
Hello all. I have had trouble getting files through proxy, and the solution posted above only works if the requested file is also hosted on the proxy server (which is quite unlikely). so I've put together the following functions pfopen & preadfile. they quite work like the replaced fopen & readfile, and will resort to them if no proxy is provided :)

<?php
function preadfile($_url, $_proxy_name = null, $_proxy_port = 4480){
  if(
is_null($_proxy_name) || LOCAL_TEST){
    return
readfile($_url);
  }else{
   
$proxy_cont = '';

   
$proxy_fp = pfopen($_url, $_proxy_name, $_proxy_port);
    while(!
feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
   
fclose($proxy_fp);

   
$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
    echo
$proxy_cont;
    return
count($proxy_cont);
  }
}
function
pfopen($_url, $_proxy_name = null, $_proxy_port = 4480) {
  if(
is_null($_proxy_name) || LOCAL_TEST){
    return
fopen($_url);
  }else{
   
$proxy_fp = fsockopen($_proxy_name, $_proxy_port);
    if (!
$proxy_fp) return false;
   
$host= substr($_url, 7);
   
$host = substr($bucket, 0, strpos($host, "/"));

   
$request = "GET $_url HTTP/1.0\r\nHost:$host\r\n\r\n";

   
fputs($proxy_fp, $request);

    return
$proxy_fp;
  }
}
?>
up
0
simon dot allen at swerve dot co dot nz
7 years ago
using fopen to upload a file through ftp cannot overwrite that file - use curl instead
up
0
ceo at l-i-e dot com
8 years ago
If you need fopen() on a URL to timeout, you can do like:
<?php
  $timeout
= 3;
 
$old = ini_set('default_socket_timeout', $timeout);
 
$file = fopen('http://example.com', 'r');
 
ini_set('default_socket_timeout', $old);
 
stream_set_timeout($file, $timeout);
 
stream_set_blocking($file, 0);
 
//the rest is standard
?>
up
0
admin at sellchain dot com
9 years ago
TIP: If you are using fopen and fread to read HTTP or FTP or Remote Files, and experiencing some performance issues such as stalling, slowing down and otherwise, then it's time you learned a thing called cURL.

Performance Comparison:

10 per minute for fopen/fread for 100 HTTP files
2000 per minute for cURL for 2000 HTTP files

cURL should be used for opening HTTP and FTP files, it is EXTREMELY reliable, even when it comes to performance.

I noticed when using too many scripts at the same time to download the data from the site I was harvesting from, fopen and fread would go into deadlock. When using cURL i can open 50 windows, running 10 URL's from each window, and getting the best performance possible.

Just a Tip :)
up
0
durwood at speakeasy dot NOSPAM dot net
9 years ago
I couldn't for the life of me get a certain php script working when i moved my server to a new Fedora 4 installation. The problem was that fopen() was failing when trying to access a file as a URL through apache -- even though it worked fine when run from the shell and even though the file was readily readable from any browser.  After trying to place blame on Apache, RedHat, and even my cat and dog, I finally ran across this bug report on Redhat's website:

https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=164700

Basically the problem was SELinux (which I knew nothing about) -- you have to run the following command in order for SELinux to allow php to open a web file:

/usr/sbin/setsebool httpd_can_network_connect=1

To make the change permanent, run it with the -P option:

/usr/sbin/setsebool -P httpd_can_network_connect=1

Hope this helps others out -- it sure took me a long time to track down the problem.
up
0
ideacode
9 years ago
Note that whether you may open directories is operating system dependent. The following lines:

<?php
// Windows ($fh === false)
$fh = fopen('c:\\Temp', 'r');

// UNIX (is_resource($fh) === true)
$fh = fopen('/tmp', 'r');
?>

demonstrate that on Windows (2000, probably XP) you may not open a directory (the error is "Permission Denied"), regardless of the security permissions on that directory.

On UNIX, you may happily read the directory format for the native filesystem.
up
0
Thomas Candrian tc_ at gmx dot ch
10 years ago
With this it isn't possible to get data from another port than 80 (and 443) - at least for me. Because of that I've made this function who gets data from every port you want using HTTP:

<?php;
function
getcontent($server, $port, $file)
{
   
$cont = "";
   
$ip = gethostbyname($server);
   
$fp = fsockopen($ip, $port);
    if (!
$fp)
    {
        return
"Unknown";
    }
    else
    {
       
$com = "GET $file HTTP/1.1\r\nAccept: */*\r\nAccept-Language: de-ch\r\nAccept-Encoding: gzip, deflate\r\nUser-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)\r\nHost: $server:$port\r\nConnection: Keep-Alive\r\n\r\n";
       
fputs($fp, $com);
        while (!
feof($fp))
        {
           
$cont .= fread($fp, 500);
        }
       
fclose($fp);
       
$cont = substr($cont, strpos($cont, "\r\n\r\n") + 4);
        return
$cont;
    }
}
echo
getcontent("www.myhost.com", "81", "/"));
?>

Works fine for me. Had to do this especially for a shoutcast server, which only delivered the HTML-file if the user-agent was given.
up
0
ken dot gregg at rwre dot com
11 years ago
PHP will open a directory if a path with no file name is supplied. This just bit me. I was not checking the filename part of a concatenated string.

For example:

<?php
$fd
= fopen('/home/mydir/' . $somefile, 'r');
?>

Will open the directory if $somefile = ''

If you attempt to read using the file handle you will get the binary directory contents. I tried append mode and it errors out so does not seem to be dangerous.

This is with FreeBSD 4.5 and PHP 4.3.1. Behaves the same on 4.1.1 and PHP 4.1.2. I have not tested other version/os combinations.
up
0
dan at cleandns dot com
11 years ago
<?php
#going to update last users counter script since
#aborting a write because a file is locked is not correct.

$counter_file = '/tmp/counter.txt';
clearstatcache();
ignore_user_abort(true);     ## prevent refresh from aborting file operations and hosing file
if (file_exists($counter_file)) {
  
$fh = fopen($counter_file, 'r+');
    while(
1) {
      if (
flock($fh, LOCK_EX)) {
        
#$buffer = chop(fgets($fh, 2));
        
$buffer = chop(fread($fh, filesize($counter_file)));
        
$buffer++;
        
rewind($fh);
        
fwrite($fh, $buffer);
        
fflush($fh);
        
ftruncate($fh, ftell($fh));    
        
flock($fh, LOCK_UN);
         break;
      }
   }
}
else {
  
$fh = fopen($counter_file, 'w+');
  
fwrite($fh, "1");
  
$buffer="1";
}
fclose($fh);

print
"Count is $buffer";

?>
up
0
Anonymous
12 years ago
Note that if specifying the optional 'b' (binary) mode, it appears that it cannot be the first letter for some unaccountable reason. In other words, "br" doesn't work, while "rb" is ok!
up
-1
webmaster at myeshop dot fr
6 years ago
Also a small function useful for backup for example. It's a mixed between the fopen() and the mkdir() functions.

This function opens a file but also make the path recursively where the file is contained. This is helpful for ending to finish with "No such file or directory in" errors

<?php
function fopen_recursive($path, $mode, $chmod=0755){
 
preg_match('`^(.+)/([a-zA-Z0-9]+\.[a-z]+)$`i', $path, $matches);
 
$directory = $matches[1];
 
$file = $matches[2];

  if (!
is_dir($directory)){
    if (!
mkdir($directory, $chmod, 1)){
    return
FALSE;
    }
  }
return
fopen ($path, $mode);
}
?>
up
-1
sergiopaternoster at tiscali dot it
10 years ago
If you want to open large files (more than 2GB) that's what I did and it works: you should recompile your php with the CFLAGS="-D_FILE_OFFSET_BITS=64" ./configure etc... This tells to your compiler (I tested only gcc on PHP-4.3.4 binary on Linux and Solaris) to make the PHP parser binary large file aware. This way fopen() will not give you the "Value too large for defined data type" error message.
God bless PHP
ciao
Sergio Paternoster
up
-1
Brad G
4 years ago
While adding CFLAGS="-D_FILE_OFFSET_BITS=64" immediately before calling "./configure" on the PHP source will enable support for using fopen() on large files (greater than 2 GB), note that -- if such an installation of PHP is used in conjunction with Apache HTTPD [2.x], Apache will become completely unresponsive even when not serving output from a PHP application.

In order to gain large file support for non-web applications while maintaining the operability of Apache, consider making two distinct PHP installations:  one with the above CFLAGS specified during configuration (for non-web uses), and the other without this flag (for use with Apache).
up
-1
info at NOSPAMPLEASE dot c-eagle dot com
7 years ago
If there is a file that´s excessively being rewritten by many different users, you´ll note that two almost-simultaneously accesses on that file could interfere with each other. For example if there´s a chat history containing only the last 25 chat lines. Now adding a line also means deleting the very first one. So while that whole writing is happening, another user might also add a line, reading the file, which, at this point, is incomplete, because it´s just being rewritten. The second user would then rewrite an incomplete file and add its line to it, meaning: you just got yourself some data loss!

If flock() was working at all, that might be the key to not let those interferences happen - but flock() mostly won´t work as expected (at least that´s my experience on any linux webserver I´ve tried), and writing own file-locking-functions comes with a lot of possible issues that would finally result in corrupted files. Even though it´s very unlikely, it´s not impossible and has happened to me already.

So I came up with another solution for the file-interference-problem:

1. A file that´s to be accessed will first be copied to a temp-file directory and its last filemtime() is being stored in a PHP-variable. The temp-file gets a random filename, ensuring no other process is able to interfere with this particular temp-file.
2. When the temp-file has been changed/rewritten/whatever, there´ll be a check whether the filemtime() of the original file has been changed since we copied it into our temp-directory.
2.1. If filemtime() is still the same, the temp-file will just be renamed/moved to the original filename, ensuring the original file is never in a temporary state - only the complete previous state or the complete new state.
2.2. But if filemtime() has been changed while our PHP-process wanted to change its file, the temp-file will just be deleted and our new PHP-fileclose-function will return a FALSE, enabling whatever called that function to do it again (ie. upto 5 times, until it returns TRUE).

These are the functions I´ve written for that purpose:

<?php
$dir_fileopen
= "../AN/INTERNAL/DIRECTORY/fileopen";

function
randomid() {
    return
time().substr(md5(microtime()), 0, rand(5, 12));
}

function
cfopen($filename, $mode, $overwriteanyway = false) {
    global
$dir_fileopen;
   
clearstatcache();
    do {
       
$id = md5(randomid(rand(), TRUE));
       
$tempfilename = $dir_fileopen."/".$id.md5($filename);
    } while(
file_exists($tempfilename));
    if (
file_exists($filename)) {
       
$newfile = false;
       
copy($filename, $tempfilename);
    }else{
       
$newfile = true;
    }
   
$fp = fopen($tempfilename, $mode);
    return
$fp ? array($fp, $filename, $id, @filemtime($filename), $newfile, $overwriteanyway) : false;
}

function
cfwrite($fp,$string) { return fwrite($fp[0], $string); }

function
cfclose($fp, $debug = "off") {
    global
$dir_fileopen;
   
$success = fclose($fp[0]);
   
clearstatcache();
   
$tempfilename = $dir_fileopen."/".$fp[2].md5($fp[1]);
    if ((@
filemtime($fp[1]) == $fp[3]) or ($fp[4]==true and !file_exists($fp[1])) or $fp[5]==true) {
       
rename($tempfilename, $fp[1]);
    }else{
       
unlink($tempfilename);
        if (
$debug != "off") echo "While writing, another process accessed $fp[1]. To ensure file-integrity, your changes were rejected.";
       
$success = false;
    }
    return
$success;
}
?>

$overwriteanyway, one of the parameters for cfopen(), means: If cfclose() is used and the original file has changed, this script won´t care and still overwrite the original file with the new temp file. Anyway there won´t be any writing-interference between two PHP processes, assuming there can be no absolute simultaneousness between two (or more) processes.
up
-1
RobNar
11 years ago
This is an addendum to ibetyouare at home dot com's note about Apache directory permissions.  If you are on a shared host and cannot tweak Apache's permissions directives then you might try setting the same thing in a .htaccess file.  Failing that, if you are having trouble just creating files then  set the directory permissions to allow writing (for whatever directory the file is supposed to be in) and include the following before fopen():

`touch /path/to/myfile/myfile.txt`;

That will usually create a new empty file that you can write to even when fopen fails. - PHP 4.3.0
up
-1
Anonymous
11 years ago
To overwrite a file with a new content without deleting it, and without changing the owner or access rights, it's best to not use:

<?php
$file
= fopen($filename, 'r+b'); // binary update mode
//...
ftruncate($file, 0);
fwrite($file, $my_stuff);
//...
fclose($file);
?>

but instead the faster one:

<?php
$file
= fopen($filename, 'r+b); // binary update mode
//...
rewind($file);
fwrite($file, $my_stuff);
fflush($file);
ftruncate($file, ftell($file));
//...
fclose($file);
?>

The reason is that truncating a file at size 0 forces the OS to deallocate all storage clusters used by the file, before you write your content which will be reallocated on disk.

The second code simply overwrites the existing content where it is already located on disk, and truncates any remaining bytes that may exist (if the new content is shorter than the old content). The "r+b" mode allows access for both read and write: the file can be kept opened after reading it and before rewriting the modified content.

It'
s particularly useful for files that are accessed often or have a size larger than a few kilobytes, as it saves lots of system I/O, and also limits the filesystem fragmentation if the updated file is quite large.

And
this method also works if the file is locked exclusively once opened (but I would rather recommend using another empty file for locking purpose, opened with "a+" access mode, in "/var/lock/yourapp/*" or other fast filesystems where filelocks are easily monitored and where the webserver running PHP is allowed to create and update lock files, and not forgetting to close the lock file after closing the content file).
up
-1
nefertari at nefertari dot be
9 years ago
Important note:

You have always to use the real path name for a file with the command fopen [for example: fopen($filename, 'w')], never use a symbolic link, it will not work (unable to open $filename).
up
-1
richard dot quadling at carval dot co dot uk
10 years ago
The issue involving some sites requiring a valid user-agent string when using fopen can easily be resolved by setting the user_agent string in the PHP.INI file.

If you do not have access to the PHP.INI file, then the use of

ini_set('user_agent','Mozilla: (compatible; Windows XP)');

should also work.

The actual agent string is up to you. If you want to identify to the sites that you are using PHP ...

ini_set('user_agent','PHP');

would do.

Regards,

Richard Quadling.
up
-1
sean downey
6 years ago
when using ssl / https on windows i would get the error:
"Warning: fopen(https://example.com): failed to open stream: Invalid argument in someSpecialFile.php on line 4344534"

This was because I did not have the extension "php_openssl.dll" enabled.

So if you have the same problem, goto your php.ini file and enable it :)
up
-4
merye at web-graphique dot com
3 years ago
I had to switch from relative paths to full paths when my web host recently migrated the server onto their hosting cloud.  This used to work for me:

<?php
$fplog
= fopen('ipn.log','a');
?>

After the migration, however, I received the following error message:

Warning: fopen(ipn.log) [function.fopen]: failed to open stream: Permission denied in D:\home\server_name\log_test.php on line 21

I had to change the code to the following to get it to work:

<?php
$logfile
= $_SERVER['DOCUMENT_ROOT'].'\\ipn.log';
$fplog = fopen($logfile,'a');
?>
up
-1
pflaume dot NOSPAM at NOSPAM dot gmx dot de
10 years ago
fopen() and PROXY

I wondered why there is no possibility to use fopen() through a proxy in php. The solution posted above did not work for me.

This little function gets http through a given proxy:

<?php
function proxy_url($proxy_url)
{
   
$proxy_name = '127.0.0.1';
   
$proxy_port = 4001;
   
$proxy_cont = '';

   
$proxy_fp = fsockopen($proxy_name, $proxy_port);
    if (!
$proxy_fp)    {return false;}
   
fputs($proxy_fp, "GET $proxy_url HTTP/1.0\r\nHost: $proxy_name\r\n\r\n");
    while(!
feof($proxy_fp)) {$proxy_cont .= fread($proxy_fp,4096);}
   
fclose($proxy_fp);
   
$proxy_cont = substr($proxy_cont, strpos($proxy_cont,"\r\n\r\n")+4);
    return
$proxy_cont;
}
?>
up
-1
Jhilton a at t nurv dot us
11 years ago
Quick tip. If using fopen to make http requests that contain a querystring, it is advised that you urlencode() your values, else characters like @ can make fopen (or whatever wrapper it is using) throw an error.
up
-1
php at themastermind1 dot com
13 years ago
I have found that I can do fopen("COM1:", "r+"); to open the comport in windows. You have to make sure the comport isn't already open or you will get a permission denied.

I am still playing around with this but you have to somehow flush what you send to the comport if you are trying to communicate realtime with a device.
up
-1
icon at mricon dot com
15 years ago
If you're running PHP as apache module, it will always write files as "nobody", "www", "httpd", (or whatever user your webserver runs as) unless you specify a different user/group in httpd.conf, or compile apache with suexec support.
However, if you run PHP as a CGI wrapper, you may setuid the PHP executable to whatever user you wish (*severe* security issues apply). If you really want to be able to su to other user, I recommend compiling with suexec support.
AFAIK, PHP can't NOT use SuEXEC if apache does. If PHP is configured as an apache module it will act as whatever user the apache is. If apache SuEXEC's to otheruser:othergroup (e.g. root:root), that's what PHP will write files as, because it acts as a part of apache code. I suggest you double-check your SuEXEC configuration and settings. Note: you can't su to another user within the PHP code -- it has to be an apache directive, either through <VirtualHost>, or through .htaccess. Also note: I'm not sure how it all works (if it works at all) on Win32 platforms.
Check www.apache.org to see how it's done.
up
-2
unshift at yahoo dot com
11 years ago
It seems that fopen() errors when you attempt opening a url starting with HTTP:// as opposed to http:// - it is case sensitive.  In 4.3.1 anyway..."HTTP://", by not matching "http://" will tell the wrapper to look locally.  From the looks of the source, the same goes for HTTPS vs https, etc.
up
-4
eyrie88 at gmail dot com
4 years ago
Be aware that fopen($url) also respects HTTP status headers. If the URL responds with a 1xx, 4xx, or 5xx status code, you will get a "failed to open stream: HTTP request failed!", followed by the HTTP status response. Same goes for file_get_contents($url)...
up
-2
keithm at aoeex dot NOSPAM dot com
13 years ago
I was working on a consol script for win32 and noticed a few things about it.  On win32 it appears that you can't re-open the input stream for reading, but rather you have to open it once, and read from there on.  Also, i don't know if this is a bug or what but it appears that fgets() reads until the new line anyway.  The number of characters returned is ok, but it will not halt reading and return to the script.  I don't know of a work around for this right now, but i'll keep working on it.

This is some code to work around the close and re-open of stdin.

<?php
function read($length='255'){
    if (!isset(
$GLOBALS['StdinPointer'])){
       
$GLOBALS['StdinPointer']=fopen("php://stdin","r");
    }
   
$line=fgets($GLOBALS['StdinPointer'],$length);
    return
trim($line);
}
echo
"Enter your name: ";
$name=read();
echo
"Enter your age: ";
$age=read();
echo
"Hi $name, Isn't it Great to be $age years old?";
@
fclose($StdinPointer);
?>
up
-5
rene
4 years ago
if fopen() throws a E_WARNING "failed to open stream: HTTP request failed!" at you when opening a valid URL that you know returns data, i advise you to do the following before calling fopen($url,'r'):

<?php
ini_set
('user_agent', $_SERVER['HTTP_USER_AGENT']);
?>

or anyways, set that 'user_agent' with ini_set() to something valid.

thanks, pollita|at|php.net @ http://bugs.php.net/bug.php?id=22937#c64196 , for the clue to this
up
-8
jphansen at uga dot edu
6 years ago
If you open a file with r+ and execute an fwrite(), writing less to the file than what it originally was, it will result in the difference being padded with the end of the file from the previous end of the file. Example:

<?php
// Open file for read and string modification
$file = "/test";
$fh = fopen($file, 'r+');
$contents = fread($fh, filesize($file));
$new_contents = str_replace("hello world", "hello", $contents);
fclose($fh);

// Open file to write
$fh = fopen($file, 'r+');
fwrite($fh, $new_contents);
fclose($fh);
?>

If the end of the file was "abcdefghij", you will notice that the difference in "hello world" and "hello", 6 characters, will be appended to the file, resulting in the new ending: "efghij". To obviate this, fopen() with +w instead, which truncates the file to zero length.
up
-5
contact at sergeylukin dot com
1 year ago
Here is how you could modify file's contents by only opening it once in "r+" mode:

<?php
$filePath
= '/path/to/file';
if( !@
$fh = fopen($filePath, 'r+') ) {
  die(
"Could not open $filePath in READ+WRITE mode");
}

// Extract contents
$contents = fread($fh, filesize($filePath));

// ..modify $contents in any way you need..

// Truncate file (important to move the pointer first)
fseek($fh, 0);
ftruncate($fh, 0);

// Write
fwrite($fh, $contents);

fclose($fh);
?>
up
-5
simon dot riget at gmail dot com
1 year ago
The following is an  example of file locking used in a function to share an array between processes.
In this example the function reads the array, possibly remove stuff like spend semaphores and insert new stuff to share.
The file gets locked for writing thus making sure that two processes doesn't inadvertently delete each others data.

The function can be called multiple times during a script, which becomes increasingly important if you write HTML5 Server Sent Events and websockets apps, since the script dose not end when the page are loaded. (there are other issues with that like garbage collection and memory leaks)
Using the “c” mode of fopen, removes the (remote) change of a race condition to the file lock.

Be aware that the function filesize() is not working correctly when files are in cash memory. You could flush the cash or in this case, since the file size of IPC are neglectable, just give a very large number as length parameter to fread.

<?php
function ipc($new_record=""){
 
$update=false;

 
// Open file with locking
 
$handle=fopen("example.dat","c+");
 
 
// Lock the file for writing
 
flock($handle,LOCK_EX);

 
// Get file size.
  // you can either fluch the file cash to get an acurate number
  // clearstatcache();
  // Or use a large number   

  // Load event file into array
 
$contents=fread($handle,10000000);

 
$ipc_array=json_decode($contents,true);

 
// Clean out old stuff
 
if(is_array($ipc_array)){
   
$timeout=time()-60
    foreach(
$ipc_array as $key=>$record){
     
// eg remove spend semaphores or timed out messages
     
if( $record['time'] < $timeout ){
        unset(
$ipc_array[$key]);
       
$update=true;
      }
    }
  }

 
// Add new message
 
if(is_array($new_record)){
   
$new_record['time']=time();
   
$ipc_array[]=$new_record;
   
$update=true;
  }

 
// Write file and end
 
if($update){
   
// Overwrite the old data
   
ftruncate($handle,0);
   
rewind($handle);
 
   
// Write the new array to file
   
fwrite($handle,json_encode($ipc_array,JSON_NUMERIC_CHECK));
  }

 
// Unlock the file - you have to do it! it doesn't happen on fclose
 
flock($handle,LOCK_UN);

 
// Close the file     
 
fclose($handle);

  return
$ipc_array;
}

// Read messages
$ipc=ipc();

// Show messages
foreach( $ipc as $record)
  echo
$record['message'] ."<br>\n";

// Send a message
$message["message"]="hello world.";
$message["foo"]="bar";
$ipc=ipc($message);
?>
To Top