PHP File Input / Output

Lesen und Schreiben von Dateien

Wie jede Programmiersprache bietet auch PHP alle Funktionen zum Lesen und Schreiben von Dateien.
Bei Verwendung von PHP zusammen mit einem Webserver betrifft das allerdings die Dateien am Server-PC !
Moderne PC verfügen über so viel Leistung, dass die Einrichtung eines 'privaten' Webservers selbstverständlich sein sollte. In diesem Fall bietet PHP die Möglichkeit, bequem über Webseiten-Programme mit allen Resourcen des eigenen PC zu arbeiten.
PHP Hypertext Processor PHP PHP Hypertext Processor
Zugriffsrechte Web-Verzeichnis: Lesen für alle, Schreiben nur in Ausnahmefällen
Pfad Der Weg zu einer Datei als String
Datei-Informationen Angaben über Existenz, Größe, Art, Alter, usw.
Text-Datei Text-Datei, Quelltext oder Live-Webseite Lesen, Schreiben, ..
Webseite Live-Webseite lesen
Binär-Datei Bytes beliebiger Werte Lesen, Schreiben, ..
Verzeichnis Durchforsten des Inhalts von Verzeichnissen
Neu & Löschen Dateien und Verzeichnisse erzeugen und löschen
Temporär Dynamische Erzeugung, jedoch mehrfache Verwendung von Dateien
Upload Download und Upload von Dateien
Zufallsnamen Zufallsnamen für Dateien

Zugriffsrechte im Web-Verzeichnis

Dieses Thema ist wichtig, weil PHP normalerweise zusammen mit einem Webserver verwendet wird.
Der Zugriff auf den Arbeitsbereich ihres Webservers sollte eingeschränkt sein. Dieser befindet sich z.B. (Linux, Windows)
/srv/www/htdocs
C:\Programme\Apache Group\Apache2\htdocs
Auf modernen Betriebssystemen ist die Ausführung jedes Programms, also auch der (Server)-Dienste an einen 'user' gebunden, danach richten sich die Zugriffsrechte des jeweiligen Programms oder Dienstes.
Als User von Diensten (services, z.B. Webserver) setzt man eigens dafür angelegte User ein.
Auf Linux läuft der Apache Webserver normalerweise unter einem eigenen User (z.B. wwwrun ). Lassen sie den Webserver keinesfalls unter dem User root laufen - jede/r Web-BesucherIn (Client) hat dann unbeschränkten Zugriff auf den gesamten Server-PC !
Für spezielle Zwecke (Upload von Dateien, Speichern von PHP-erzeugten Dateien) sollten sie eigene Bereiche mit Schreib-Rechten für den Webserver (und PHP) einrichten.
(Nur) Lese-Rechte für Alle:
Für beliebige User wird der Zugriff für Lesen und Ausführen (read+execute) erlaubt - d.h. Webserver und damit PHP-Programme können jede Datei innerhalb des Arbeitsverzeichnisses (z.B. /srv/www/htdocs/ ) lesen.
Ausserhalb dieses Verzeichnisses sollte man keine Rechte gewähren.

Schreib-Rechte nur für WebMaster:
Für die/den jeweiligen Web-AdministratorIn muss voller Zugriff ('read/write/execute') erlaubt werden, denn sonst ist keine Wartung oder Änderung des Webs möglich.
Ausnahmen:
Upload-Verzeichnis: Hier darf PHP Dateien speichern, die von Usern mit 'upload' auf den Webserver kopiert wurden.
PHP-erstellte Dateien: Hier darf PHP Dateien speichern, die 'programmgesteuert' erstellt wurden.
Geben sie die Schreibrechte für PHP oder für alle User nur auf diese Verzeichnisse frei.
Damit ist eine Sicherheits-Lücke geöffnet: Mit einigen Tricks können ungebetene Gäste als ganz normale Web-BesucherInnen Dateien in diesem Verzeichnis ändern oder löschen.
Sperren sie daher generell den Schreib-Zugriff des Apache-demon-Users und geben sie ihn nurausnahmsweise dort frei, wo das erwünscht ist.

Pfad

Ein Pfad ist ein String (Zeichenkette), welcher den Weg zu einer Datei oder zu einem Verzeichnis beschreibt.
Das aktuelle ArbeitsVerzeichnis (current working directory, cwd ) ist normalerweise jenes Verzeichnis, in welchem sich das PHP-Script selbst befindet.
PHP-Funktion getcwd gibt den absoluten Pfad zum aktuellen Verzeichnis zurück. Mit Funktion chdir kann man das aktuelle Verzeichnis ändern.
Die Konstante __FILE__ gibt den absoluten Pfad zur eigenen Script-Datei zurück, Funktion dirname isoliert daraus das Verzeichnis, Funktion basename den Dateinamen. Mit → Regulären Ausdrücken kann man die Pfade weiter analysieren.
Live--PHP:
getwcd() = srv/www/htdocs/entwicklung/php/inout
__FILE__ = srv/www/htdocs/entwicklung/php/inout/inout.php
dirname(__FILE__) = srv/www/htdocs/entwicklung/php/inout
basename(__FILE__) = inout.php
$f = preg_split("/\./",basename(__FILE__));
$f[0] = inout
$f[1] = php
Ein relativer Pfad beschreibt den Weg zu einer Datei, ausgehend vom ↑ aktuellen Verzeichnis cwd
Das Trennzeichen (Linux /, Windows \) wird durch die Konstante DIRECTORY_SEPARATOR angegeben.
Der rel.Pfad (hier $rp) zu einer Datei im aktuellen Verzeichnis cwd enthält nur den Dateinamen.
Der rel.Pfad zu einer Datei in einem Unterverzeichnis enthält zusätzlich das Unterverzeichnis.
Der rel.Pfad zu einer Datei in einem übergeordneten Verzeichnis enthält ../ für jeden Sprung in ein höheres Verzeichnis.
HTML-Links zu eigenen Webseiten (des gleichen Webs) verwenden relative Pfade zur Angabe des Sprungziels.

Verwenden sie in einfachen Fällen relative Pfade, z.B. für alle Dateien im gleichen Verzeichnis wie das Script.
$sep = DIRECTORY_SEPARATOR;
// im gleichen Verzeichnis
$rp = 'test.dat';
// Unterverzeichnis
$rp = 'sub/test.dat';
// Überverzeichnis
$rp = '../test.dat';
// Komplex
$rp = '../../sub1/sub2/test.dat';
Live-Live-PHP-PHP:
DIRECTORY_SEPARATOR = /
Ein absoluter Pfad beschreibt den Weg zu einer Datei, ausgehend von der Wurzel des gesamten Dateisystems. Der Pfad beginnt stets mit einem / Zeichen.
Manche Sicherheits-Maßnahmen schreiben die Verwendung absoluter Pfade vor.
Das Beispiel zeigt, wie man absolute Pfade programmieren kann, ausgehend vom eigenen Pfad eines Scripts. Das Ergebnis ist auf andere Webserver portabel.
$myap = __FILE__;
$ap = preg_replace('/php.*$/','',$myap);
$ap.= 'buffer/test.dat';
So entsteht aus dem String
/srv/www/htdocs/.../php/file_info.php
der gewünschte String
/srv/www/htdocs/.../buffer/test.dat
Ein Webserver-Alias ist ein Text, welcher einen absoluten Pfad bezeichnet. Alias-Text und Pfad werden in der Server-Konfiguration eingestellt. Man kann für einen Webserver beliebig viele Alias anlegen. Das meist-verwendete Alias ist /cgi-bin
Damit wird (stellvertretend) ein Pfad angegeben, der sich irgendwo (an sicherer Stelle) am Server-PC befindet. Normale AnwenderInnen können nicht feststellen, ob es sich bei einer entfernten Web-Adresse um einen absoluten Pfad oder um ein Alias handelt.
Ein URL-Pfad beschreibt einen Internet-Pfad. Die solcherart adressierte Datei kann mit allen Standardfunktionen zum Lesen von Dateien gelesen und entsprechend verarbeitet werden.
HTML-Links zu fremden Webseiten verwenden URL-Pfade zur Angabe des Sprung-Ziels.
URL-Pfad:
$up = 'http://pstrainer.topsoft.at/';
HTML-Hyperlink:
<a href="http://pstrainer.topsoft.at">Link</a>
Entgegen einem weit verbreiteten Aberglauben kann man das http:// nicht weglassen, und es beginnen auch nicht alle Domain-Namen mit www ...
Funktion glob (ab PHP Version>4.3) filtert alle Objekte des aktuellen Verzeichnisses (cwd) mit Hilfe eines Filter-Strings und gibt ein → Array mit den Pfaden aller Treffer zurück.
Das verwendet man z.B. zur bequemen Massen-Bearbeitung von Dateien.
Der Filter des Beispiels gibt alle Dateien *.htm und *.html zurück.
$pa = glob('*.htm*');
print count($pa)." Pfade gefunden<br />\n";
foreach ($pa as $p) {
// Verarbeitung, z.B.
print $p."<br />\n";
}

Zum nächsten Kapitel Zum Inhaltsverzeichnis Zum vorigen Kapitel Verzeichnis (Ordner, folder)
Das Beispiel demonstriert, wie man mit PHP Informationen über den Inhalt eines Verzeichnisses erhalten kann.
Daszu benötigen sie mindestens Lese-Berechtigung (↑ Zugriffsrechte) im betreffenden Verzeichnis !

Das Beispiel beginnt ganz unten mit dem Aufruf der selbst erstellten Funktion dir_list() für ein Test-Verzeichnis.
Funktion dir_list() erstellt für dieses Verzeichnis eine Inhalts-Liste.
Die PHP-Funktion dir() gibt für einen gegebenen Pfad ein Verzeichnis-Objekt ($verz) zurück.
In der while-Schleife wird je ein Objekt-Name an die Variable $nam übergeben. In der Verarbeitung werden 3 Fälle (grün) unterschieden.
Als Sonderfälle treten in jeder Liste die Objekte "." und ".." auf. Sie bezeichnen das eigene und das übergeordnete Verzeichnis und werden (continue) übersprungen.
In jedem anderen Fall wird aus dem Namen ein kompletter Pfad ($path) erzeugt und anschließend untersucht.
Wenn es sich um ein Verzeichnis handelt, dann wird es an Funktion dir_list() übergeben, die sich damit selbst (rekursiv) aufruft.
Wenn es sich um eine Datei handelt, wird Name, Erzeugungs-Datum und Größe ausgegeben.

Details zu Regulären Ausdrücken (Funktion preg_match() ), Datei-Informationen (filectime(), filesize() ), Datum & Zeit (strftime() )
PHP-Funktion: Verzeichnis-Liste (vereinfacht)
function dir_list($dir) {
print "*\$dir = $dir <br />\n";
$verz = dir($dir);
while($nam=$verz->read()) {
if(preg_match('/^\./',$nam)) {continue;}
$path = $dir.'/'.$nam;
if(is_dir($path)) {
print "Verzeichnis: $path<br />\n";
dir_list($path);   // rekursiv
print "*zurueck in $dir<br />\n";
}
elseif(is_file($path)) {
print "Datei: $path, ";
$ct = filectime($path);
print strftime('%Y-%m-%d %T',$ct);
$fs = filesize($path);
print ", $fs Byte<br />\n";
}
}
$verz->close();
}
Beispiel für die Anwendung:
$test = 'testdir';
dir_list($test);
Rekursive Verfahren kommen in 'hierarchischen Bäumen' wie z.B. einem Dateisystem oft zum Einsatz.
So kann man einen (fast) beliebig komplexen Baum mit geringem Aufwand durchackern.
Für eigene Anwendungen tragen sie in den beiden bedingten Verzweigungen (is_dir(),is_file()) an Stelle der print-Befehle die gewünschten Anweisungen ein.
Windows-Freud:
Sie müssen sich nicht mit dem lästigen Backslash-\-Trennzeichen in Windows-Pfaden herumschlagen ($pfad1). Das Standard Trennzeichen / funktioniert ebenso ($pfad2).
Falls sie doch \ verwenden, dann müssen sie jeden Backslash in einem String mit einem weiteren \ maskieren ($pfad1)
// Pfad: C:\test
$pfad1 = "C:\\test";
$ok = chdir($pfad1);
$pfad2 = 'C:/test';
$ok = chdir($pfad2);
Windows-Leid:
Die Funktion dir() und verwandte Funktionen wie opendir(), chdir() funktionieren auf Windows-Systemen (nur) für lokale Volumes, nicht jedoch für 'Netzlaufwerke' - egal ob Windows- oder → Samba-Volumes. Im Internet werden dafür unterschiedliche Umgehungen angeboten.
Achtung: Alle Angaben ohne Gewähr !
Damit der Webserver (z.B. → Apache) und damit PHP auf ein Netzwerk-Volume zugreifen kann, muss der Dienst unter einem dazu berechtigten User gestartet werden.
Richten sie ein User-Konto mit Zugriff auf das gewünschte Volume ein, verwenden sie ihr persönliches Konto oder das Administratoren-Konto.
Öffnen sie das Services-Dienstprogramm (z.B. C:\Windows\System32\services.msc) und rechts-klicken sie den Webserver (z.B. Apache2).
In Eigenschaften | Anmelden stellen sie das gewünschte Konto ein.
Starten sie den Webserver-Dienst neu.
Nun können sie nach dem Muster rechts auf entfernte Volumes zugreifen.
Wenn sie einen Webserver am eigenen PC betreiben, dann ist das Sicherheits-Risiko für die hier vorgestellte Lösung nicht allzu groß. In diesem Fall sollten sie jedoch daran denken, den Zugriff auf den Webserver auf lokale User zu begrenzen. In allen anderen Fällen könnten sie über den Umstieg auf ein professionelles Server-Betriebssystem nachdenken.
/* Pfad zu einem entfernten Volume:
Server + Volume-Name + Verzeichnis
Server Name oder Adresse, z.B. '192.168.0.1'
Volume-Name auf dem Server: z.B. 'Server'
Verzeichnis auf dem Volume: z.B. 'test'
*/
$pfad1 = "\\\\192.168.0.1\\Server\\test";
$ok = chdir($pfad1);
$pfad2 = '//192.168.0.1/Server/test';
$ok = chdir($pfad2);
/* Beide Beispiele funktionieren nur dann, wenn der Webserver-User Zugriff auf den entfernten Server und sein freigegebenes Volume hat.
*/

Zum nächsten Kapitel Zum Inhaltsverzeichnis Zum vorigen Kapitel Neu-Erstellen und Löschen von Verzeichnissen und Dateien

Orientierung:

Das 'current working directory' (cwd) ist jenes Verzeichnis, auf welches sich alle relativen Pfade beziehen.
Funktion getcwd() gibt das aktuelle cwd zurück.
Funktion chdir() wechselt in das angegebene Verzeichnis und gibt den Erfolg zurück. $ok=true, wenn das Verzeichnis existiert.
$cwd = getcwd();
print "cwd = $cwd <br />";

$ok = chdir('sub');
print "cwd = $cwd <br />";

Verzeichnis neu anlegen:

Funktion mkdir() legt ein neues Verzeichnis an, wenn PHP / der Webserver das Recht dazu haben. Argumente: Dateiname und Zugriffsrechte für das neue Verzeichnis.
Die Zugriffsrechte werden in UNIX-Art als 3stellige Oktalzahl angegeben.
$ok = mkdir('neu',0777);

Verzeichnis löschen:

Funktion rmdir() löscht ein Verzeichnis (Zugriffs-Rechte vorausgesetzt) ohne Rückfrage und gibt im Erfolgsfall true zurück.
$ok = rmdir('alt');

Datei neu anlegen:

Dafür wird Funktion fopen() mit Modus {w,wb,a,ab} verwendet.
Beispiele zum Schreiben von Text- und Binär-Dateien.
$fp = fopen('test.dat','w');

Datei löschen:

Funktion unlink() löscht eine Datei ohne Rückfrage, wenn PHP / Webserver dazu berechtigt sind.
$ok = unlink('test.dat');

Letzte Änderung dieser Seite: 2011-11-30 13:04:46