hannes: php Bild-Datei wird nicht gelöscht

Hallo, ich kann eine Datei nicht löschen und die Lösung nicht finden. Der Code ist:

<?php

$dir = "../../news_docs/";
$thumbdir = "../../news_docs/thumbs/";
chmod($dir, 777);

$docs = array();
$pics = array();

$result_1 = mysqli_query($connect, "SELECT uploadfiles, uploadpics FROM ".$dbtable." WHERE id = '".$_GET['id']."' ");
list($uploadfiles,$uploadpics) = mysqli_fetch_array($result_1);

//Teilt den String (Trennstelle: Komma-Zeichen) und erstellt ein Array

$docs = explode(',',$uploadfiles);
$pics = explode(',',$uploadpics);

foreach($docs as $value_docs){

	if(!empty($value_docs)){

		if (!unlink($dir.$value_docs)){

			echo "
			  <head><META HTTP-EQUIV='refresh' content='3;URL=xyz.php'></head>
			  <table class='error'>
			  <tr>
				<td>Dokument <span style='font-weight:bold; color:#777;'>".$value_docs."</span> konnte nicht gel&ouml;scht werden!</td>
			  </tr>
			  </table>
			  ";
			exit;
		}

	}
}

?>

kann mir bitte jemand helfen?

  1. Tach!

    ich kann eine Datei nicht löschen und die Lösung nicht finden. Der Code ist:

    Viel zu viel Code. Das Löschen ist genau ein Funktionsaufruf. Anderer Code ist dafür nicht relevant. Der eine Funktionsaufruf ist so einfach, dass das Nicht-Löschen-Können nicht am PHP Code liegt.

    Vielleicht ist es ein Nebenproblem, zum Beispiel dass der Dateinamen nicht richtig ist. Aber das kann man mit einer Kontrollausgabe überprüfen und ausschließen. Auch Logikprobleme, dass der Programmablauf nicht beim Löschaufruf ankommt, kann man mit Debugging klären. Einem Außenstehenden stehen die konkreten Werte nicht zur Verfügung, mit denen dein Script läuft.

    Aber vielleicht ist es ein Rechteproblem, das kannst du dann nicht mit PHP-Code beheben, sondern nur administrativ.

    Jedenfalls gibt unlink() über den Rückgaberwert bekannt, wenn es selbst ein Problem hat. Dazu gibt es auch eine E_WARNING, in der man einen hinweis zur Ursache finden kann.

    chmod($dir, 777);

    Was sollen das für Rechte sein? Einem 'rwxrwxrwx' entspricht das jedenfalls nicht, denn das wäre 0777. Und müssen überhaupt sämtliche Benutzer in dem Verzeichnis schreiben können?

    dedlfix.

  2. Hallo hannes,

    Die Funktion error_get_last() liefert dir ein Array mit 4 Einträgen zum letzten aufgetretenen Fehler. Damit solltest du die Ursache eingrenzen können. Eigentlich sollte der Fehler auch im Error-Log des Servers landen, aber viele Hoster verstecken den…

    Dein fehlerhaftes chmod() ist ein guter Kandidat für Rechteprobleme. 777 dezimal entspricht der Oktalzahl 1411, d.h. Leserecht für den Owner, und für alle anderen nur Execute-Rechte. Hinzu kommt das Sticky-Bit, dessen Funktion für meinen kleinen Windows-Kopf zu abstrus ist. Die führende Null bei Oktalwerten zu vergessen ist ein beliebter Fehler.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Ich konnte das Problem lösen (Fehler in einer Variablen-Zuschreibung). Vielen Dank trotzdem für die Hinweise zu den Rechten. mfg

  3. Hallo Hannes,

    auch wenn das Problem bereits gelöst ist, neben den bereits erwähnten Dingen noch ein paar Hinweise/Tipps:

    $result_1 = mysqli_query($connect, 
      "SELECT uploadfiles, uploadpics 
       FROM ".$dbtable." WHERE id = '".$_GET['id']."' "
    );
    

    Das was du hier machst ist gefährlich: du darfst Daten nicht einfach so in einen Query einbauen, du handelst dir damit eine SQL-Injection-Lücke ein. Ein »1' or '1« in $_GET['id'] führt dann zur Bedingung »WHERE id = '1' or '1'«, womit der Query alle Datensätze liefert. Dadurch dass du mysqli_fetch_array nur einmal aufrufst würde zwar immer noch nur ein Datensatz (bzw. die Bilder dazu) gelöscht – wenn auch u.U. der falsche Datensatz. Du musst Kontextwechsel immer behandeln, ich würde prepared Statements in Verbindung mit PDO empfehlen (siehe Link).

    Außerdem: Aktionen die Daten verändern bzw. löschen sollten immer per POST-Request aufgerufen werden, nie per GET-Request wie das bei dir der Fall ist, siehe Wiki.

    //Teilt den String (Trennstelle: Komma-Zeichen) und erstellt ein Array
    
    $docs = explode(',',$uploadfiles);
    $pics = explode(',',$uploadpics);
    

    Dein Datenbankdesign scheint mir nicht in Ordnung zu sein, ein Datensatz sollte nur einen Wert enthalten – beschäftige dich mit dem Thema Normalisierung.

    foreach($docs as $value_docs){
    
    	if(!empty($value_docs)){
    
    		if (!unlink($dir.$value_docs)){
    
    			echo "…
    

    Ein Tipp am Rande: Code ist besser lesbar wenn er möglichst wenig eingerückt wird (und die Zeilen nicht zu lang sind). Hier lässt sich das umsetzen indem du die beiden Bedingungen zusammenfasst oder sie umdrehst und mit continue arbeitest:

    foreach($docs as $value_docs){
      if(empty($value_docs) or unlink($dir.$value_docs)){
        continue;
      }
      echo "…";
    }
    

    <td>Dokument […] konnte nicht gel&ouml;scht werden!</td>

    Es gibt keinen Grund mehr Umlaute zu verstümmeln, schreibe sie einfach direkt hin – immer und überall mit UTF-8 zu arbeiten sollte inzwischen selbstverständlich sein.

    ?>

    Wenn nicht noch HTML ausgegeben werden soll wird empfohlen das ?> weg zu lassen – damit verhinderst du Probleme mit versehentlich ausgegebenen Leerzeichen/Zeilenumbrüchen.

    Gruß
    Tobias