facebraker
Goto Top

Kann in DB gespeicherte Daten nicht mehr auslesen

Hallo,

ich habe vor Jahren mit einen kleinen Projekt angefangen, soll ein Extranet werden.
Mitarbeiter können Dateien hochladen und Kunden können die Dateien bei sich herunterladen.

Jedenfalls habe ich es wieder aufgegriffen und versuche es wieder auf die Beine zu stellen.

Das hochladen der Dateien funktioniert perfekt, das herunterladen nicht.

Ich habe einen Button, der eine PHP Datei aufruft, mit einer Action "download" und der ID der Datei in der
Mysql Datenbank:

if($_GET['todo']==download) {  
    $id_files=$_GET['id'];  
    $connectionid = mysql_connect ("localhost", "user", "password");   
    if (!mysql_select_db ("intranet", $connectionid)) {   
        die ("Keine Verbindung zur Datenbank");   
    } 
    $sql = "SELECT content, type, name, size FROM upload WHERE id=$id_files";  
         	
    $result = @mysql_query($sql, $connectionid);
    if ( !$result ) die('MySQL-Fehler:' . mysql_error()); 	  
    $data = @mysql_result($result, 0, "content");  
    $name = @mysql_result($result, 0, "name");  
    $size = @mysql_result($result, 0, "size");  
    $type = @mysql_result($result, 0, "type");  
	
    header("Content-type: $type");  
    header("Content-length: $size");  
    header("Content-Disposition: attachment; filename=$name");  
    header("Content-Description: PHP Generated Data");  
    echo $data;
    mysql_close($connectionid);
}

Eigentlich sollte ich ja dann einen Datei-Download bekommen, läuft aber nicht face-sad

Was mache ich falsch?

Danke Gruß Alex

Content-ID: 195880

Url: https://administrator.de/contentid/195880

Ausgedruckt am: 22.11.2024 um 14:11 Uhr

firefly
firefly 14.12.2012 um 16:53:40 Uhr
Goto Top
Hi @facebraker,

lass Dir als erstes doch mal die $sql Variable ausgeben und überprüfe damit dann die Datenbank. Dann würde ich auch die "@" Zeichen vor den "mysql_" Befehlen löschen, da das @ mögliche Fehlermeldungen unterdrückt. So von der Syntax sollte es korrekt sein.

Gruß
@firefly
bytecounter
bytecounter 14.12.2012 um 19:19:05 Uhr
Goto Top
Moin,

also ich stell mir erst einmal die Frage, was kommt denn überhaupt? Wenn kein Download kommt, muss ja ein Warning, eine Exception oder sonst was kommen.

Könnte mir auch vorstellen, dass Dein Script noch auf einer alten PHP-Version basiert, der Server aber zwischenzeitlich auf einer neueren Version läuft.

vg
facebraker
facebraker 14.12.2012 um 19:23:28 Uhr
Goto Top
Hallo Firefly, ich habe das Skript mal schön gemacht.

<?php
error_reporting( -1 );
ini_set('display_errors', TRUE);  

session_start (); 
#include ("checkuser.php");  
#echo $_GET ['id']; 
#echo $_SESSION["user_id"]; 
if(isset($_GET['id']) && isset ($_SESSION["user_id"]))    
{
  $connectionid = mysql_connect ("localhost", "user", "password");  
  #echo $_GET['todo']; 
  if($_GET['todo']==download)  
  {
      $id_files=$_GET['id'];  
      if (!mysql_select_db ("intranet", $connectionid)) die ("Keine Verbindung zur Datenbank");   
        $sql = "SELECT content, type, name, size FROM upload WHERE id=$id_files";  
        $result = mysql_query($sql, $connectionid);
      echo $sql;
      if ( !$result ) die('MySQL-Fehler:' . mysql_error());     
      $data = mysql_result($result, 0, "content");  
      $name = mysql_result($result, 0, "name");  
      $size = mysql_result($result, 0, "size");  
      $type = mysql_result($result, 0, "type");  
        
      #header("Content-type: $type"); 
      #header("Content-length: $size"); 
      #header("Content-Disposition: attachment; filename=$name"); 
      #header("Content-Description: PHP Generated Data"); 
      echo $data;
      
    }
    elseif ($_GET['todo']==delete)  
    {
        $id_files=$_GET['id'];  
        if (!mysql_select_db ("intranet", $connectionid)) die ("Keine Verbindung zur Datenbank");   
      $sql = "DELETE FROM upload WHERE id=$id_files";  
        $result = mysql_query($sql, $connectionid);
        if ( !$result ) die('MySQL-Fehler:' . mysql_error());     
     }
    mysql_close($connectionid);
    Header('Location: projekt_portal.php');  
  }
?>

Komischerweise wird kein "echo" ausgegeben, auch nicht als Debug, könnte das der Fehler sein?

Gruß Alex
bytecounter
bytecounter 14.12.2012 um 19:43:52 Uhr
Goto Top
Versteh ich jetzt nicht...ein echo als debug? Also entweder da ist ein echo, dann wird das auch ausgegeben - oder da ist eben keins.

Wenn er schon in Zeile 19 nix ausgibt, dann passt da was nicht. Ist das das komplette Script? Rufst Du das direkt auf? Oder gibt's da vorher noch was?
Zeile 19 würde ich vor Zeile 18 schreiben. Danach mal ein exit; Dann muss er ja zumindest die Query ausgeben.

vg
nxclass
nxclass 14.12.2012 aktualisiert um 23:08:43 Uhr
Goto Top
beachte dass gewisse Wörter zum SQL Syntax von MySQL gehören.
SELECT `content`, `type`, `name`, `size`
FROM `upload`
WHERE `id`= $id_files
... um Problemen mit dem Escape der Parameter auszuschließen würde ich Dir empfehlen bind zu nutzen oder gleich PDO.

EDIT:
  • benutze lieber var_dump() für debug ausgaben
  • if($_GET['todo']==download) ... was ist download ? - eine Konstante ? ... ich glaube nicht. benutze mal error_reporting(E_ALL);
facebraker
facebraker 16.12.2012 um 12:25:32 Uhr
Goto Top
Hallo!

Ich habe eure Anmerkungen z.T. umgesetzt.

if($_GET['todo']==download) ist wirklich dämlich face-sad natürlich muss es if($_GET['todo']=='download') heißen, aber ich wundere mich warum es trotzdem im "delete" Zweig geht?

Ja, das Skript ist nicht alles.

Ich habe eine Seite, wo in einer Tabelle die Dateien in der DB angezeigt sind, in jeder Zeile sind 2 Button "Download" und "Delete" , wenn der Nutzer "Delete" drückt, wird das Skript aufgerufen und die "id" des Datensatzes in der DB übergeben und die "userid". Beim "Download" das gleiche ... aber der Download klappt sind, es passiert einfach nichts, wenn ich "Download" klicke sagt der Browser "warten auf localhost (WAMP)" und weiter nichts.

Meine Vermutung, das "echo $data" wird zwar ausgeführt aber irgendwie geblockt, Browser oder PHP???? Keine Ahnung.

Das mit mysqli und PDO muss ich auch umsetzen, aber mit Laptop und keiner richtigen Tastatur und Maus ist das nervig, wenn dann schaffe ich es Montag am Schreibtisch face-wink

Aber abgesehen von der Anfälligkeit für SQL Injenctions muss es ja funktionieren.

Gibt es im PHP eine globale Variable die Fehlermeldungen auf ein mindest Log-Level setzt, dass ich kein Feedback bekomme?

Gruß Alex
facebraker
facebraker 16.12.2012 um 13:12:15 Uhr
Goto Top
Hi habe jetzt auf mysqli umgestellt, erstmal nur den "download" Zweig, aber keine Änderung.

<?php
#error_reporting( -1 );
error_reporting(E_ALL);
ini_set('display_errors', TRUE);  

session_start (); 
#include ("checkuser.php");  
#echo $_GET ['id']; 
#echo $_SESSION["user_id"]; 
if(isset($_GET['id']) && isset ($_SESSION["user_id"]))    
{
	$connectionid = mysqli_connect ("localhost", "intranet", "intranet");  
	#echo $_GET['todo']; 
	if($_GET['todo']=='download')  
	{
			$id_files=$_GET['id'];  
			if (mysqli_connect_errno($connectionid)) {
    			echo "Failed to connect to MySQL: " . mysqli_connect_error();  
				}
	  		$sql = "SELECT 'content', 'type', 'name', 'size' FROM upload WHERE 'id'=$id_files";  
	  		var_dump( $sql);
	  		if ($result = mysqli_query($connectionid, $sql)) {

		    /* fetch associative array */
    		while ($row = mysqli_fetch_assoc($result)) {
        			$name = $row["name"];  
        			$size =  $row["size"];  
        			$type =  $row["type"];  
        			$data=  $row["content"];  
        	}

    		/* free result set */
    		mysqli_free_result($result);
			}

			header("Content-type: $type");  
			header("Content-length: $size");  
			header("Content-Disposition: attachment; filename=$name");  
			header("Content-Description: PHP Generated Data");  
			echo $data;
	}
	  mysqli_close($connectionid);
	  Header('Location: projekt_portal.php');  
  }
?>



*Grübel* geht nicht, wieder keine Reaktion, baue ich Fehler ins Skript, dann kriege ich Fehlermeldungen, aber so nicht.

Gruß Alex
nxclass
nxclass 16.12.2012 aktualisiert um 20:52:35 Uhr
Goto Top
Beachte die Backticks ` - nicht die Hochkommas ' verwenden im SQL, dann gibt dir die SELECT Anweisung die Tabellen Feldnamen als Konstanten zurück.

EDIT:
  • Wenn deine DB Verbindung fehlschlägt - wird nach dem IF() trotzdem weitergearbeitet. - daher ein exit() oder throw new Exception() einfügen
  • In WHILE: var_dump( $row )
  • Wenn deine SQL Anweisung einen Fehler produziert - also $result === false ist - was dann ? - eine Ausgabe des SQL Errors würde bestimmt gut in einen ELSE Zweig passen
bytecounter
bytecounter 16.12.2012 aktualisiert um 21:50:24 Uhr
Goto Top
Hallo,

man kann die Ausgabe mit PHP zwar nicht blocken, aber z. B. mit ob_start() erst einmal zurückhalten. Sobald das Script aber beendet wird, wird alles ausgegeben, was im Puffer steht. Allerdings kann dieser zwischendrin auch z. B. mit ob_clean() ohne Ausgabe geleert werden. Da sehe ich in Deinem Script aber nicht; dazu könnte natürlich in dem aufrufenden Script was stehen.

Um den Fehler zu suchen, könntest Du ein einfaches Script schreiben, welches Du direkt im Browser aufrufst. Dort sind keine IFs und keine $_GETs..sondern einfach nur z. B.
$id = 5;
$dbh = mysqli_connect ("localhost", "intranet", "intranet");   
$query = "SELECT * FROM upload WHERE id=$id";  
echo "Query: $query <br>";  
$result = mysqli_query($dbh, $query);
var_dump($result);

Dann mal schauen, was er dazu sagt.

vg
bytecounter
bytecounter 17.12.2012 um 09:56:56 Uhr
Goto Top
Sowas ähnliches hatte er vorher schon, allerdings mit die(); was ja grundsätzlich auf das gleiche rauskommt. Ist zwar auch nicht sauber, aber das Script ist ja auch schon älter ;)

Mein gestern gepostete Script sollte etwas Licht ins Dunkel bringen. Die Sache mit den Backticks hab ich auch schon vermutet. Daher hab ich das in meinem Bsp "anders" gelöst. Mal schauen, was facebraker postet.

Euch allen eine angenehme und stressfreie Vorweihnachtswoche!

vg
Bytecounter
facebraker
facebraker 17.12.2012 um 12:21:41 Uhr
Goto Top
Hallo Bytecounter & nxclass,

ich hatte gestern Abend richtig die Schnautze voll, und frei nach der Debugging-Regel "Wenn was nicht funktioniert, gehe davon aus, dass das komplette Skript fehlerhaft ist" habe ich noch einmal von Null angefangen.

Das das Skript nicht so spektakulär war, habe ich es von Anfang an versucht sauber zu programmieren.

ABER, ich denke mal nxclass hat recht mit den Backticks, denn in meinen neuen Skript verwende ich ein Select * from upload WHERE... Das könnte der Fehler sein. Denn viel anders mache ich es in den neuen Skript auch nicht.
Bis auf mysqli_* und mysqli_real_escape_string ..


Jedenfalls mein neues funktioniert, vielen Dank für Eure Tipps!

<?php 
session_start (); 
// DB
$link = mysqli_connect("localhost", "intranet", "intranet","intranet");   

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());  
    exit();
}

if (isset($_GET['id']) &&  isset ($_SESSION["user_id"])) {   
	if($_GET['todo']=='download'){  
		// SQL String
		$sql = sprintf("SELECT * FROM upload WHERE id = '%s' LIMIT 1", mysqli_real_escape_string($link,$_GET['id']));  
		if ($result = mysqli_query($link, $sql)) {

				/* fetch associative array */
				while ($row = mysqli_fetch_assoc($result)) {
					printf ("%s (%s)\n", $row["Name"], $row["CountryCode"]);  
					// Den Browser zum Download zwingen 
					header("Content-type: " . $row["type"]);   
					header("Content-disposition: attachment; filename=".$row["name"].";");   
					header("Content-length: " . $row["size"]);   

					// Daten dekodieren und an den Browser senden 
					echo $row["content"];   

				}

				/* free result set */
				mysqli_free_result($result);
			}
		
		/* close connection */
		mysqli_close($link);
		exit; 
		}
	elseif ($_GET['todo']=='delete') {  
		$sql = sprintf("DELETE FROM upload WHERE id='%s'",mysqli_real_escape_string($link,$_GET['id']));  
	  	$result = mysqli_query($link,$sql);
	  	if ( !$result ) die('MySQL-Fehler:' . mysqli_error($link)); 	  
		}
		Header('Location: http://localhost/extranet/projekt_portal.php');  
} 
?>


Gruß Alex
bytecounter
bytecounter 17.12.2012 um 12:57:21 Uhr
Goto Top
Freut mich, dann den Thread bitte noch als gelöst markieren.

Allerdings noch ein Tip: Um das Script ein wenig abzusichern, solltest Du keine Variablen direkt (also ungefiltert) an den SQL übergeben.
Bei einer ID (welche vermutlich ein Integer ist), ist das recht einfach:

$id = (int) $_GET['id'];

Ist es ein String, müsstest Du ihn auf erlaubte Zeichen prüfen. Da Du das aber nur intern einsetzt- und ich vermute, dass der Server von außen gar nicht erreichbar ist, ist das nicht ganz so dramatisch.

Weiterhin viel Erfolg!

vg
Bytecounter
facebraker
facebraker 17.12.2012 um 15:05:10 Uhr
Goto Top
Hallo Bytecounter,

Danke für den Tipp, da habe ich mich schon belesen und es wurde empfohlen dies zu nuten:

mysql_real_escape_string — Maskiert spezielle Zeichen innerhalb eines Strings für die Verwendung in einer SQL-Anweisung

http://php.net/manual/de/function.mysql-real-escape-string.php

Natürlich ist deine Lösung, so einfach wie genial face-smile

Aber mysql_real_escape_string sollte auch reichen, oder?

Danke, ich bin schon am nächsten Problem, würde mich freuen wenn du die Augen im Forum offen hälst und mir eventuell da helfen kannst.

Vielen Dank!

Gruß Alex
bytecounter
bytecounter 18.12.2012 um 00:26:33 Uhr
Goto Top
Hallo Alex,

das kannst Du natürlich auch nehmen.

vg
Bytecounter