Newsgroup: it.comp.www.php
Titolo: estrarre un'immagine da mysql, aiutatemi sto impazzendo!!!

Ciao a tutti,
Ho inserito in un db mysql, in campi blog, delle immagini tramite
codice php. Va tutto bene, con mysql front quando clicco sul campo del
db vedo in anteprima l'immagine.
Ho provato ad estrarre le stesse immagini con codice php ma non ci
riesco.
Ho letto faq, tutorial, guide, documenti, ma niente, non funziona un
bel niente!!!!
Quando richiamo l'immagine o mi escono caratteri incomprensibili o un
piccolo riquadro con una x dentro, come quando si fa riferimento ad
un'immagine il cui collegamento è sbagliato.
Aiutatemi sto impazzendo, vi riporto il codice:
INSERIMENTO:
...
$nome = $_POST['verif_nome'];
$gruppo = $_POST['gruppo'];
$alt_tag = $_POST['verif_alt'];
$img = $_POST['img'];
$data_mod = "NOW()";
$size = $_FILES['verif_img']['size'];
$type = $_FILES['verif_img']['type'];
$estensione = strrchr($_FILES['verif_img']['name'],".");
$nome_tmp = $_FILES['verif_img']['tmp_name'];
// memorizzo il il contenuto del file in una variabile
$dati_img = file_get_contents($nome_tmp);
//eseguo il quoting del contenuto della variabile
$dati_img = addslashes($dati_img);
//preparo la query per l'inserimento dell'immagine e dei dati annessi
$query = 'INSERT INTO img SET nome = "'.$nome.'",
		img = "'.$dati_img.'",
		gruppo = '.$gruppo.',
		mime_type = "'.$type.'",
		alt = "'.$alt_tag.'",
		size = '.$size.',
		estensione = "'.$estensione.'",
		id_ext_operatore = '.$_SESSION['idoperatore'].',
		data_mod = '.$data_mod;
$result = QueryDB($query);
QueryDB è semplicemente una funzione che esegue la query e funziona di
sicuro.
ESTRAZIONE:
<?php
if (isset($_GET['id']))
{
  $id = @intval($_GET['id']);
  $sql = "SELECT id,mime_type,img FROM img WHERE id='$id'";
  $result = QueryDB($sql);
  $row = @mysql_fetch_array($result);
  $id_img = $row['id'];
  $type = $row['type'];
  $img = $row['immagine'];
  if (!$id_img)
  {
    echo "Id sconosciuto";
  }else{
    @header ("Content-type: ".$type);
    echo $img;
  }
}else{
  echo "Impossibile soddisfare la richiesta.";
}
?>

 codice php. 
è veramente una cosa brutta, se puoi evitala
almeno secondo i miei particolari gusti.
pensa ai backup dei database ad esempio...
-- 
777 fanno 21, arriva la volante e non c'è nessuno


Ma 2 immagini da pochi byte....
cavolo neanche così le recupera!
<?php
// query per recuperare il file
$query = 'SELECT * FROM img WHERE id = '.$_GET['id'];
$risultato = QueryDB($query);
$tmp = mysql_fetch_array($risultato);
// invio una intestazione contenente il tipo MIME
header('Content-Type: '.$tmp['mime_type']);
// invio il contenuto del file
echo $tmp['img'];
?>

 
Per il resto credo vada bene.
Have a nice day,
David
-- 
 . ''`.  Debian maintainer | 
http://snipurl.com/gofoxygo/
 : :'  :  Linuxer #334216  |  
http://www.hanskalabs.net/
 `. `'`    GPG: 1392B174   | 
http://www.debianizzati.org/
   `-   2BAB C625 4E66 E7B8 450A C3E1 E6AA 9017 1392 B174


Ho trovato il problema....
se includo un file che contiene le variabili di connessione al db non
funziona se invece le inserisco manualmente e non lo includo funziona
tutto correttamente!
Solo che non posso inserire i dati di accesso al db manualmente!
Come posso fare???

Come posso fare???
Trova l'errore in quell'altro file, mi pare chiaro.
Per esempio: non e' che manda fuori degli header?
Leonardo
-- 
 What do you make, so fair and bright;
 What do you build with sails for flight;
 What do you weave with wool so white?

 Per esempio: non e' che manda fuori degli header?
Ma contiene solo delle variabili, ora provo a commentare una riga per
volta così verifico!


Basta anche uno spazio prima del <?PHP per scombussolare gli header
	Francesco

Ho provato ad includere questo file:
<?php
//parametri configurazione database
$db_host = "000.000.000.000";
$db_user = "user";
$db_password = "passw";
$db_name = "nomedb";
?>
E non funziona! Se non includo questo file ma inserisco i dati
direttamente nel file di richiamo dell'immagine invece l'immagine
viene visualizzata correttamente!!! Ma com'è possibile????


Ma ti riferisci al file incluso o a quello che include?
Comunque ho annullato commenti, spazi e includo solo delle variabili
(vedi posto precedente) non riesco a capire come sia possibile!!
Ma c'e' un modo per resettare l'header e reimpostarlo??

 ha scritto nel messaggio 
news:f5t6ko$req$1...@newsserver.cilea.it...

concordo, al 99% il problema è un output prima dell'header (se proprio non 
hai volgia di cercarlo dovrebbe essere sufficiente un ob_start() all'inizio)
non sono invece d'accordissimo sull'assunzione che le img (o altri blob) nel 
db siano così negativi, un punto a favore, imho, è proprio il discorso 
backup, cioè salvando il db io mi porto già dietro i file altrimenti dovrei 
backuppare sia il db che cartella upload/ o altro...i punti negativi invece 
quali sarebbero?
ciao
Mario
_________________________
WEB: 
www.mario-online.com
________________________________ 

 
Ne abbiamo già discusso!
Contro: database di grandi dimensioni, minor velocità del dbms rispetto 
al fs (con cache di quest'ultimo), limitazioni sullo spazio db rispetto 
allo spazio fs fornite dai vari hosting C'era qualcos'altro ma non ricordo!
	Francesco

 hai volgia di cercarlo dovrebbe essere sufficiente un ob_start() all'inizio)
cavolo!!! era una riga vuota!!!
Beh tenendo conto che può succedere di lasciare una riga vuota nel
file di conf utilizzerò ob_start() e ob_end_flush()
Grazie per l'aiuto!!!

> file di conf utilizzerò ob_start() e ob_end_flush()
Ehmmmm si ma come si usano??? :(
Ho letto la documentazione di php ma non l'ho capito...
mi potete fare un esempio di utilizzo per il mio caso??
Grazie 1000


Mi sembra un modo per raggirare il problema, non di risolverlo!
A mali estremi, prova a copiare il codice su un altro file (una volta ho 
risolto proprio in questo modo: peccato non avevo un editor hex per 
vedere cosa c'era di strano!)
All'interno del codice ci possono essere spazi/tab righe vuote ma fuori 
dal tag <?PHP non deve esserci niente!
	Francesco


Ma per me va bene, il problema è che come faccio a spiegarlo
all'utente finale?
Mi tartasseranno ogni volta che modificando il file di conf
inseriranno inavvertitamente uno spazio vuoto!
con ob_start() non risolverei il problema???

C'era qualcos'altro ma non ricordo!
ok ok...;)..vado a spulciarmi un po di post per vedere cosa dicevate..





Una riga vuota prima di <?php oppure dopo ?>. O uno spazio dopo ?>:
?> <-- c'e' uno spazio, e ti fa danno
?><-- non c'e', e funziona
<?php deve essere la PRIMA riga del file, e ?> l'ULTIMA. Nel mezzo ci
puoi mettere quello che ti pare, basta non contenga print, echo e via
discorrendo.


Francesco F ha scritto:

scusate se mi permetto di rispolverare la cantina...:
http://www.ludovicocaldara.net/computer/ImageIntoDB.pdf
il discorso è da rivedere sui FS di nuova generazione. i benchmark che 
avevo fatto diversi anni fa sarebbero da rifare. in ogni caso, pro e 
contro sono ancora equivalenti, imho. dipende sempre da quante immagini 
devi caricare e di che dimensioni.
ciao
-- 
punkarruso

 il discorso č da rivedere sui FS di nuova generazione. 
Ho buttato giů tre righe di codice per fare un test molto semplice:
in una directory ho inserito diverse immagini (1656/500/100 immagini per 
un totale di 60 Mbyte), ho caricato queste nel database (tabella 
nomefile/image); tramite due script eseguiti via bash ho estratto i nomi 
delle immagini dal db e eseguito l'output via db e via fs. Per il tempo, 
ho utilizzato il cmd time di unix.
Anche per il test su fs prelevo i nomi del file dal db (per avere lo 
stesso numeri di accessi al database).
Questo č il codice:
   $DB_link = mysql_connect(...) or die("MysqlConnect");
   mysql_select_db(...) or die("DB Select error");
   $stderr = fopen('php://stderr', 'w');
   $lista_image = null;
   //carico in un array la lista dei nomi prelevati dal db
   $sql = "Select nomefile from tmp order by nomefile;";
   $res = mysql_query($sql) or die(mysql_error());
   while($row = mysql_fetch_assoc($res)) {
     $lista_image[] = $row['nomefile'];
   }
   if($_SERVER['argc'] == 2) {
     switch ($_SERVER['argv'][1]) {
       case 'load':
         load($lista_image);
         break;
       case 'test_fs':
         test_fs($lista_image);
         break;
       case 'test_db':
         test_db($lista_image);
         break;
       default:
         echo 'Action: load | test_fs | test_db' . "\n";
      }
   } else {
     echo 'Action: load | test_fs | test_db' . "\n";
   }
   $mex = 'Prova '. $_SERVER['argv'][1] . ', '. count($lista_image) . ' 
immagini';
   fwrite(STDERR, $mex);
   function test_fs($lista_image) {
     foreach ($lista_image as $filename) {
       $sql = "Select nomefile from tmp where nomefile='" . 
mysql_real_escape_string($filename) . "';";
       $res = mysql_query($sql) or die(mysql_error());
       $fp = fopen(mysql_result($res, 0, 0), 'rb');
       fpassthru($fp);
     }
   }
   function test_db($lista_image) {
     foreach ($lista_image as $filename) {
       $sql = "Select image from tmp where nomefile='" . 
mysql_real_escape_string($filename) . "';";
       $res = mysql_query($sql) or die(mysql_error());
       echo mysql_result($res, 0, 0);
     }
   }
   function load($lista_image) {
     mysql_query("Delete from tmp;") or die(mysql_error());
     foreach (glob("*.gif") as $filename) {
         echo "$filename size " . filesize($filename) . "\n";
         $sql ="Insert into tmp (nomefile, image) values('" . 
mysql_real_escape_string($filename) . "','" . 
mysql_real_escape_string(file_get_contents($filename)) . "');";
         $res = mysql_query($sql) or die(mysql_error());
     }
   }
Il risultato č il seguente:
[root@srv9 tmp]# time php -q test.php test_fs > /dev/null
Prova test_fs, 1656 immagini.
real 0m2.165s
user 0m0.491s
sys  0m0.555s
[root@srv9 tmp]# time php -q test.php test_db > /dev/null
Prova test_db, 1656 immagini.
real 0m3.663s
user 0m0.826s
sys  0m0.464s
[root@srv9 tmp]# time php -q test.php test_fs > /dev/null
Prova test_fs, 500 immagini.
real 0m0.713s
user 0m0.183s
sys  0m0.166s
[root@srv9 tmp]# time php -q test.php test_db > /dev/null
Prova test_db, 500 immagini.
real 0m1.131s
user 0m0.286s
sys  0m0.156s
[root@srv9 tmp]# time php -q test.php test_fs > /dev/null
Prova test_fs, 100 immagini.
real 0m0.208s
user 0m0.100s
sys  0m0.041s
[root@srv9 tmp]# time php -q test.php test_db > /dev/null
Prova test_db, 100 immagini.
real 0m0.295s
user 0m0.119s
sys  0m0.044s
Macchina:
Pentium III, 866 MHz, 512 Mbyte, CentOS5, ext3
PHP 5.2.1 (cli) (built: Apr 19 2007 09:07:01)
Mysql Server version: 5.0.22-log
	Francesco

 ha scritto nel messaggio
news:1182870123.4...@o11g2000prd.googlegroups.com...



<?php



srtipslaches ?
echo $tmp['img'];
?>

echo $tmp['img'];
Alle perse, prova ad archiviare l'immagine dopo averla
codificata in base64. Cosi' non ti servono escape, non
hai problemi di codifica e via dicendo.



grande Francesco, con i numeri si può ragionare, in effetti si, ragionando 
sui benchmark l'accesso su file system è più veloce (mi pare su 100 img 
abbiamo ben 0,09 sec di differenza...;) ritornando invece alle 
considerazioni pratiche ( lo so che nel precedente post parlavo di teoria e 
su questo ci siamo chiariti: è più veloce l'accesso senza MySQL) 
consideriamo una classica applicazione web che mostra delle paginate di 
immagini (1, 5, 10, 20 per pagina), sarà così più veloce l'accesso via file 
system da farmi abbandonare la facilità di backup dei data di MySQL ?
ovvio non ti chiedo di scrivere un altro benchmark ..;)
ciao e buon we


 
fs -7% system
il punto a cui volevo arrivare già nel mio post precedente non è tanto 
la velocità di leggere un file tramite FS (che sempre fread è), quanto 
la velocità del FS nel fare l'inode lookup del file su una quantità di 
immagini molto elevata. in particolare, stendendo il white-paper 
sull'argomento avevo tenuto conto del punto empirico di collasso della 
gestione lineare degli inode dei filesystem, che 4 anni fa era evidente 
arrivando a 20000 immagini nella stessa directory.
mentre un accesso indicizzato su una tabella di 1Mln record ti estrae il 
record in pochissimo tempo, potresti avere dei problemi a fare una fopen
sullo atessa quantità di files, a meno che non si usino strutture inode 
ad albero o filesystem distribuiti.
ciao
-- 
punkarruso

 
Domani, voglio fare un altro paio di prove sull'ordine dei 20000 record 
(come hai giustamente sottolineato, punto nevralgico dei fs)
Se mi avanzano 10 minuti, vorrei fare delle prove anche tramire ab 
(apache benckmark) per vedere il comportamento dei due sistemi nei casi 
di alto traffico.
	Francesco

 ovvio non ti chiedo di scrivere un altro benchmark ..;)
Nel rapporto costi/benefici se preferisci la facilità del db per la 
gestione dati, sono saranno certo decimi di secondo che fanno scegliere 
l'altra strada. Resta da provare cosa succede, come hai suggerito te, 
per poche immagini per pagina nel caso di alto traffico. Domani cerco di 
fare altre prove, se posso!
	Francesco

 
Con qualche giorno di ritardo ho fatto altre prove: rispetto la volta 
precedente, non posso utilizzare time in quanto, per simulare un uso 
ordinario (come suggerito da Mario), ho fatto uno script per estrapolare 
un'immagine (attraverso due parametri: fs|db e id immagine), più una 
pagina contenitore che estrae (random) 5 immagini e esegue un 
file_get_contents all'url dello script per l'estrazione.
Alla fine, mi mancano i vari header per la corretta visualizzazione 
dell'immagine ma, questo non dovrebbe "impattare" sui risultati del test.
Pagina per l'estrazione dell'immagine (get_image.php):
$DB_link = mysql_connect('127.0.0.1', ..., ...) or die("MysqlConnect");
mysql_select_db('tmp', $DB_link) or die("DB Select error");
if($_GET['type'] == 'fs') {
   $sql = 'select nomefile from tmp where 
tmp.id
 = ' . $_GET['id'] ;
   $res = mysql_query($sql) or die(mysql_error());
   $filename = mysql_result($res, 0, 0);
   if(file_exists($filename)) {
     $fp = fopen($filename, 'rb');
     header("Content-Type: image/gif");
     header("Content-Length: " . filesize($filename));
     fpassthru($fp);
  } else {
     die("File $filename not found!");
   }
}elseif($_GET['type'] == 'db') {
   $sql = 'select nomefile, image from tmp where 
tmp.id
 = '.$_GET['id'] ;
   $res = mysql_query($sql) or die(mysql_error());
   $image = mysql_result($res, 0, 0);
   header("Content-Type: image/gif");
   header("Content-Length: " . strlen($image));
   echo $image;
}
Pagina contenitore:
   $DB_link = mysql_connect('127.0.0.1',..,..) or die("MysqlConnect");
   mysql_select_db('tmp', $DB_link) or die("DB Select error");
   $count = mysql_result(mysql_query("Select count(*) from tmp;"), 0, 0);
   for($i=0; $i < 5; $i++) {
     $image[$i] = rand(1,$count);
   }
   $type = $_GET['type'];
   foreach ($image as $key=>$value) {
     $url = '
http://127.0.0.1/tmp/get_image.php
';
     echo file_get_contents($url . '?type=' . $type . '&id=' .$value);
  }
  echo 'Fine';
Test eseguito con ab -n 100 
http://127.0.0.1/tmp/index.php
Numero immagini: 33120 (dimensione totale: 1,195 Gbyte)
Risultati test (eseguiti più volte, ho fatto una semplice media)
Riga Time taken for tests, AB:
Con DB: 10,587 secondi
Con FS: 19,781 secondi
Interessante monitorare tramite top lo stato del sistema:
DB: mysql resta al 10-15% del processore, cpu iowait a 50-60%
FS: mysql a 2-5% del processore, cpu iowait 80%
	Francesco

 un'immagine (attraverso due parametri: fs|db e id immagine), piů una 

se posso perň ti farei notare come, imho, per un paragone effettivo si 
potrebbe evitare del tutto l'accesso al db per il ramo 'fs' cioč qualcosa 
del tipo (non consideriamo qua i discorsi di sicurezza input etc per favore)
$base_path = "/dovestannoleimg/";
if($_GET['type'] == 'fs') {
   $filename = $basepath.$_GET['id'].".gif";
   if(file_exists($filename)) {
     $fp = fopen($filename, 'rb');
     header("Content-Type: image/gif");
     header("Content-Length: " . filesize($filename));
     fpassthru($fp);
  }
dato che altrimenti nel 'fs' hai cmq un accesso MySQL come nel 'db'
ciao
PS: grazie per il tempo che dedichi a ciň .. .;)


 
Anche nel precedente test avevo messo l'accesso al db per la prova sul 
fs, per un semplice motivo: la necessità di mostrare l'alt text 
dell'immagine.
	Francesco