(tratto dal sito: http://www.mmkit.com)
PHP MySQL - Trasferire files con le funzioni FTP -
Download:
Tempo fa realizzai un (mini)programma per un progetto
didattico inerente le funzioni ftp.
Successivamente lo rimaneggiai e lo riadattai ad un contesto di tipo lavorativo
aggiungendovi delle funzioni di gestione 'multiutenza' e 'superutenza'.
Con questo articolo ho deciso di pubblicare il codice e di renderlo disponibile
a chiunque ne avesse necessità.
Il programma è autoconfigurante e ciò comporta che per creare il DB col quale
esso si relaziona, è sufficente richiamare il file "configurazione.php" e
seguire la procedura guidata (ho cercato di renderla il più possibile
user-friendly :-) ).
Lo script di configurazione interroga il server MySQL per verificare l'esistenza
del DB e in caso di risposta negativa ne creerà uno nominandolo come deciso
dall'utente.
Simultaneamente verrà scritto un file (conf.php) contenente le variabili che
saranno poi utilizzate per la connessione ftp (se già esistente verrà
sovrascritto).
L'ultimo step prevede la creazione della tabella necessaria e la creazione
dell'account "superuser".
Fatto questo se tutto sarà andato a buon fine, si passerà alla pagina index.php
contente l'area di checklogin e il link al pannello/modulo di registrazione dei
singoli utenti.
Nota: (Il trasferimento dei files è possibile farlo solo se loggati come utenti
normali e non come superutente. Il Superutente può solamente accedere alle
cartelle dei singoli utenti ed eseguire il download o l'eliminazione dei
rispettivi files.)
Tra le altre cose il software comprende uno script che visualizza il contenuto
delle singole cartelle in una pagina web con i links per il download e la
cancellazione-eliminazione dello stesso file.
Premessa:
Il codice è modificabile in ogni sua parte e, poichè si tratta comunque di una
versione DEMO che ha il puro e semplice scopo di fornire un valido esempio a
coloro che devono creare piccole applicazioni ftp, potrebbe presentare alcuni
bugs. Ho utilizzato anche un metodo poco ortodosso per la rinominazione di
cartelle e files. (Lascio a voi lo studio di una soluzione alternativa ;-) ).
PHP MySQL - Upload Immagini - Download:
Con questo articolo invece vediamo come utilizzare il PHP per
effettuare l'upload, modificare e cancellare immagini da un database MySQL.
L'esempio tratta immagini ed swf, ma è facilmente adattabile a qualsiasi tipo di
file.
Parte del codice che ho utilizzato per scrivere questo tutorial è tratto
dall'articolo "File
uploads made easy" di Darren Beale, ma in buona parte è stato modificato per
interfacciarlo ad un database.
L'esempio, che potete scaricare cliccando sul tasto per il download, è formato
da 2 files php:
- upload.php
- getdata.php
Il file principale è il primo, dato che contiene tutto il codice per la gestione
delle immagini.
Da premettere che i file sono perfettamente funzionanti (a condizione di una
giusta configurazione dei parametri di connessione al db), ma per comprendere
appieno il codice occorre avere già una infarinata di PHP, dato che non mi
soffermerò troppo sul significato dei comandi utilizzati.
La prima cosa da fare è definire una serie di variabili globali (come l'esempio
di Beale):
$my_max_file_size = "307200"; //sarebbero 300Kb
$image_max_width = "400"; // in pixel
$image_max_height = "500"; // in pixel
$registered_types = array(
"application/x-gzip-compressed" => ".tar.gz, .tgz",
"application/x-zip-compressed" => ".zip",
"application/x-tar" => ".tar",
"text/plain" => ".html, .php, .txt, .inc",
"image/bmp" => ".bmp, .ico",
"image/gif" => ".gif",
"image/pjpeg" => ".jpg, .jpeg",
"image/jpeg" => ".jpg, .jpeg",
"application/x-shockwave-flash" => ".swf",
"application/msword" => ".doc",
"application/vnd.ms-excel" => ".xls",
"application/octet-stream" => ".exe, .fla" );
Di tutte queste ne utilizziamo solo le seguenti:
$allowed_types = array("image/gif","image/pjpeg","image/jpeg","application/x-shockwave-flash");
Seguono poi tutte una serie di funzioni che verranno utilizzate a seconda delle
operazioni da svolgere.
In realtà la prima istruzione che viene eseguita si trova alla riga 201:
dbconnect();
Richiama la funzione relativa alla connessione al database MySQL:
function dbconnect() {
mysql_connect("db_host", "db_username", "db_password");
@mysql_select_db("db_name") or die ("Unable to select database");
}
Sono le uniche righe da configurare per il corretto funzionamento del programma.
Nel database, creiamo una tabella che chiameremo mmkit_images
con i seguenti campi:
id int(11) NOT NULL auto_increment,
bin_data longblob,
filename varchar(255),
filesize varchar(50),
filetype varchar(50),
filewidth varchar(50),
fileheight varchar(50),
PRIMARY KEY (id)
che contengono rispettivamente i dati binari del file, il nome, la dimensione in
byte, il tipo di file (jpg, gif, swf), la larghezza e l'altezza.
Nell'allegato è presente un file SQL, che se eseguito (ad esempio con phpMyAdmin)
crea in automatico la tabella ed i relativi campi.
Ritornando al file upload.php, segue uno switch per richiamare la funzione
desiderata:
switch($task) {
case 'upload':
upload($thefile);
break;
case 'delete':
delete($id);
break;
case 'mod':
mod($id);
break;
case 'change':
change($thefile, $id);
break;
default:
form($error);
}
Appena partiamo la funzione richiamata è
form()
, dove è presente la form per l'invio delle immagini.
Il codice HTML è il seguente:
<form ENCTYPE="multipart/form-data" action="upload.php"
method="post">
<INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="307200">
<INPUT TYPE="hidden" name="task" value="upload">
<br><b>File</b>: <INPUT NAME="thefile" TYPE="file" SIZE="35"><br>
<br><input type="submit" Value="Invia">
</form>
La prima cosa da notare è che per poter inviare file al server è necessaria una
form con il parametro ENCTYPE="multipart/form-data"
.
É importante anche il campo <INPUT TYPE="hidden"
name="MAX_FILE_SIZE" value="xxx">
che definisce la dimensione
massima del file da inviare. Da notare che comunque non sempre basta questo
parametro per evitare l'upload di file giganteschi (infatti controlleremo sempre
il file che arriva al server prima di inserirlo nel db), ma è una riga
necessaria per il corretto funzionamento dell'upload.
Fate poi attenzione a non alzare troppo questo valore: in genere un database
MySQL di default può accettare dati per un massimo di 2Mb per ogni campo
LONGBLOB
, ma può essere settato anche a meno. Quindi per conoscere qual è
la dimensione massima dei file che potete inserire nel db dovete contattare
l'amministratore del server che vi fornisce il servizio. In genere si può
arrivare senza problemi a gestire file di 8Mb, ma sinceramente non ho mai
provato.
La form punta sempre al file upload.php, ma come campo hidden abbiamo la
variabile task=upload
, che tramite lo
switch visto poc'anzi richiamerà la funzione upload()
.
Una cosa molto interessante è che con questo tipo di form, il file inviato lo
ritroviamo nella variabile $thefile
,
ma con esso ritroviamo in automatico anche le seguenti variabili (tutte global):
$thefile_name
,
$thefile_size
, che contengono il nome del file e la sua
dimensione (in byte).
Per sapere invece le dimensioni in pixel dell'immagine basta eseguire:
$size = GetImageSize($thefile);
questa funzione restituisce (in una serie di valori contenuti in un array) le
dimensione di immagini GIF, JPG, PNG, SWF, SWC, PSD, TIFF, BMP e IFF.
Per maggiori info
php.net.
Preleviamo le variabili che ci interessano con un list:
list($foo,$width,$bar,$height) = explode(""",$size[3]);
così da avere in $width
e
$height
la larghezza e l'altezza del
file. Delle altre variabili possiamo farne a meno
Detto questo possiamo capire il funzionamento della funzione
upload()
:
per prima cosa viene eseguito un test tramite la funzione
validate_upload()
per controllare se la dimensione in byte o
in pixel dell'immagine sia contenuta nei limiti che abbiamo prefissato. Per i
file swf (data la loro natura vettoriale), invece ho inserito un
ridimensionamento automatico se le dimensioni risultano maggiori di quelle
stabilite.
Le nuove variabili globali $g_height
e
$g_width
vengono quindi settate alle
dimensioni da inserire nel database.
Se l'immagine è accettata viene letta ed inserita nel db tramite questo codice:
$fp=@fopen($thefile, "r");
if ($fp){
$data = addslashes(fread($fp, filesize($thefile)));
$result=MYSQL_QUERY("UPDATE mmkit_images SET bin_data='$data',
filename='$thefile_name', filesize='$thefile_size', filetype='$thefile_type',
filewidth='$g_width',
fileheight='$g_height' WHERE id=$id");
fclose($fp);
if (!$result) { echo mysql_errno(). ": ".mysql_error(). " "; exit();}
else Header("Location: upload.php");
} else { ...errore... }
Viene letto il file con il comando fopen
(il @ prima di esso fa in modo di non stampare un messaggio di errore in caso di
problemi... solamente per una sorta di pulizia del risultato dato che tutti i
messaggi di errore sono inseriti con un echo), e dopo aver spostato il contenuto
nella variabile $data
viene inserito
nel database con una query.
Se tutto è andato bene si viene reindirizzati su upload.php, altrimenti viene
stampato un errore.
Per visualizzare le immagini invece c'è la funzione list_files():
function list_files() {
$result=mysql_query("select id, filename, filetype, filewidth, fileheight from
mmkit_images");
if (mysql_num_rows($result) > 0) {
echo"<table width="98%" border="1" cellspacing="1"cellpadding="1" bordercolor="#000000">
<tr bgcolor="#999999"><td>Files presenti nel database:</td></tr>";
while(list($id, $filename, $filetype, $width, $height)=mysql_fetch_row($result))
{
echo"<tr bgcolor="#cccccc"><td><a href="upload.php?task=delete&id=$id">Delete</a>
- <a href="upload.php?task=mod&id=$id">Modify</a></td></tr>";
if (ereg("flash", $filetype)) {
echo"<tr bgcolor="#FFFFFF"><td><object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=5,0,0,0"
width="$width" height="$height"><param name=movie value="getdata.php?id=$id">
<param name=quality value=high><embed src="getdata.php?id=$id" quality=high
pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
type="application/x-shockwave-flash" width="$width" height="$height">
</embed></object></td></tr>";
} else {
echo"<tr bgcolor="#FFFFFF"><td><img src="getdata.php?id=$id"
width="$width" height="$height"></td>
</tr>";
}
}
echo"</table>";
} else echo"<br>Il database è vuoto.";
}
Vengono presi tutti i record presenti nella tabella e viene stampato un codice
HTML diverso a seconda se il file che dobbiamo visualizzare è di tipo immagine o
di tipo Flash. Notiamo che nei relativi attributi src è inserito il file
getdata.php?id=$id
. Questo file è
quello delegato a prendere i dati binari e a creare un header adatto.
Il codice del file getdata.php è tutto qui:
function dbconnect() {
mysql_connect("db_host", "db_username", "db_password");
@mysql_select_db("db_name") or die ("Unable to select database");
}
dbconnect();
if($id) {
$query = "select bin_data, filetype FROM mmkit_images WHERE id='$id'";
$result = @MYSQL_QUERY($query);
$data = @MYSQL_RESULT($result,0,"bin_data");
$type = @MYSQL_RESULT($result,0,"filetype");
Header("Content-type: $type");
echo $data;
};
Infatti dopo la connessione al database, viene prelevata l'immagine ed il
relativo filetype e viene inviato un nuovo content-type relativo al tag html che
si sta eseguendo ed il suo contenuto.
Una volta che eseguite i files in allegato troverete anche la possibilità di
eliminare o di cambiare un'immagine. Il codice è piuttosto semplice (si tratta
solamente di eseguire delle query):
$result=MYSQL_QUERY("UPDATE mmkit_images SET
bin_data='$data', filename='$thefile_name', filesize='$thefile_size', filetype='$thefile_type',
filewidth='$g_width', fileheight='$g_height' WHERE id=$id");
per l'aggiornamento di un'immagine e
mysql_query("delete from mmkit_images WHERE id=$id");
per la sua cancellazione.
Vi ricordo che per un corretto funzionamento dei files in allegato, il server
che userete deve supportare il PHP, dovete avere accesso ad un database MySQL su
cui dovete aver creato la tabella con le caratteristiche presenti nel file
mmkit_images.sql (basta eseguirlo con phpMyAdmin oppure con una query in php) e
dovete configurare i parametri di connessione al db nei file upload.php (righe
28-29) e getdata.php (righe 3-4).
Inoltre i file upload.php e getdata.php si devono trovare nella stessa
directory.
Il codice inoltre si presta alla possibilità di usare e gestire anche altri tipi
di file (.zip ad esempio): basta fare poche modifiche ed eliminare la parte
relativa alle dimensionamento in pixel del file.
Aggiornamento 20 settembre 2004
La sintassi usata nell'esempio considera la variabile register_globals su
on.
Dato che la sintassi è già indicata come deprecated, conviene usare le variabili
super global per la gestione delle variabili provenienti da una form.
Quindi le vairabili provenienti dalla form per la selezione del file vanno presi
e gestiti con $_REQUEST o $_POST (ad esmepio $_POST['task'], invece di $task),
mentre il file viene gestito con la variabile $_FILES:
$thefile_name diventa $_FILES['thefile']['name']
$thefile_size diventa $_FILES['thefile']['size']
$thefile_type diventa $_FILES['thefile']['type']
Per maggiori info sulla variabile $_FILES
clicca qui
PHP MySQL - Invio mail con allegati - Download:
Alcuni giorni fa, per finire un lavoro, ho dovuto preparare
una form per l'invio di un curriculum da mandare, insieme ai dati richiesti, ad
un determinato indirizzo mail. Non avevo mai affrontato il problema degli attach,
ma sapevo che la cosa non era difficile, dato che esiste una vasta
documentazione in merito... Ovviamente mi sbagliavo: ho perso una mattinata
intera. Così ho deciso di scrivere questo tutorial sperando di far risparmiare
tempo a chi ha lo stesso problema. In allegato inoltre è disponibile un file php
perfettamente funzionante (c'è da cambiare solo l'indirizzo e-mail del
destinatario).
Questo esempio tratta l'invio di una serie di dati (nome, cognome, email,
ecc...) insieme ad un curriculum in formato .doc.
Per prima cosa quindi prepariamo la form che deve essere del tipo:
<form enctype="multipart/form-data" method="post" action="nome_pagina.php"
name="contatti">
ed oltre ai campi testuali, inseriamo anche la parte per la selezione del file .doc:
<input type="hidden" name="MAX_FILE_SIZE" value="102400">
<input name="thefile" type="file" SIZE="35">
Il campo hidden MAX_FILE_SIZE è obbligatorio per il corretto
funzionamento del tutto, ed esprime la dimensione massima del file da inviare
(in questo caso 100Kb). Nota che comunque viene fatto un ulteriore controllo
prima di spedire la mail.
Una volta inviati i dati, vengono fatti i dovuti controlli sui campi obbligatori
e sul file inviato (vengono accettati solo i files .doc).
Se tutto va bene viene preparata la mail.
Per inviare una mail con attach è necessario agire sugli header per impostare un
messaggio in più parti: una parte che contiene il testo della mail ed un'altra
che contiene i dati del file allegato.
L'header è del tipo:
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="XX-1234DED00099A"
Content-Transfer-Encoding: 7bit
From: $email
ed il messaggio del tipo:
--XX-1234DED00099A
---Testo del messaggio---
--XX-1234DED00099A
Content-Type: application/octet-stream; name="curriculum.doc"
Content-Transfer-Encoding: base64
Content-Description: "Curriculum"
Content-Disposition: attachment
---Curriculum in codifica base64---
--XX-1234DED00099A--
Il comando php per inviare una mail è il seguente:
mail("Email del destinatario", "Oggetto della mail", "Messaggio", "Headers")
Quindi l'header diventa:
$headers = "MIME-Version: 1.0\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"XX-1234DED00099A\"\n";
$headers .= "Content-Transfer-Encoding: 7bit\n";
$headers .= "From: $email\n";
Ed il messaggio:
$messaggio="--XX-1234DED00099A\n";
$messaggio.="Content-Type: text/plain; charset=iso-8859-1\n";
$messaggio.="Content-Transfer-Encoding: 7bit\n\r";
$messaggio.="Testo della mail"
$messaggio.="--XX-1234DED00099A\n";
$messaggio.="Content-Type: application/octet-stream; name=\"curriculum.doc\"\n";
$messaggio.="Content-Transfer-Encoding: base64\n";
$messaggio.="Content-Description: \"Curriculum\"\n";
$messaggio.="Content-Disposition: attachment\n\r";
$fp=@fopen($thefile, "r");
if ($fp) { $data = fread($fp, filesize($thefile)); }
$curr = base64_encode($data);
$messaggio .= "$curr";
Ed il gioco è fatto.
La parte in blu è relativa alla trasformazione del file in codifica base64.
Note
Una delle cose che mi ha causato più problemi è stato il fatto che nei vari siti
di riferimento per la documentazione delle mail multipart, le
intestazioni delle varie parti del messaggio hanno come caratteri per andare a
capo \n\r.
Il doppio uso di \r e \n dipende dal fatto che il carattere di
"nuova linea" non è standard per tutte le piattaforme ed inserendole tutte e due
si coprono tutte le possibilità.
Purtroppo usando \n\r, tutte le mail che mi arrivavano non venivano
visualizzate nel modo giusto, perchè il carattere \r non veniva
riconosciuto.
Inserendo\r solo nei messaggi, il problema è stato risolto; quindi se vi
capita un problema analogo su altre piattaforme, dovrebbe essere il caso di
sostituire tutti gli \n con \n\r.
Il file in allegato, inoltre, comprende anche l'invio automatico di una conferma
all'indirizzo email dell'utente.
Per il corretto funzionamento del file è necessario inserire l'indirizzo mail
del destinatario alla riga 73 del file allegato a questo articolo (all'interno
della variabile $emailto).
Se volete modificare la dimensione massima del curriculum da inviare dovete
modificare il campo hidden nella form (riga 160) e la variabile
$my_max_file_size (riga 10).
Ovviamente è possibile modificare il codice per accettare altri tipi di file e
non solo i .doc. ;-)
Buon divertimento.