In questo breve tutorial, creeremo un semplice form AJAX di upload basato su jQuery, che permetterà ai visitatori di caricare dei file, un po’ come fatto in questo nostro articolo.
Le funzionalità aggiuntive rispetto al vecchio uploader sono il supporto al drag&drop (ovvero al trascinamento del file sulla finestra del browser) tramite un robustissimo plugin per jQuery, ovvero jQuery File Upload.
Fase 1 – Scheletro HTML
Come al solito, iniziamo con un documento di base, in questo caso HTML5.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Form Upload AJAX!</title>
<link href="assets/css/style.css" rel="stylesheet" />
</head>
<body>
<form id="form" method="post" action="upload.php" enctype="multipart/form-data">
<div id="drop">
Trascina qui!
<a>Carica</a>
<input type="file" name="upl" multiple />
</div>
<ul>
<!-- I file sono mostrati qui -->
</ul>
</form>
<!-- JavaScript Includes -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
<script src="assets/js/jquery.knob.js"></script>
<!-- jQuery File Upload e dipendenze -->
<script src="assets/js/jquery.ui.widget.js"></script>
<script src="assets/js/jquery.iframe-transport.js"></script>
<script src="assets/js/jquery.fileupload.js"></script>
<!-- File JavaScript -->
<script src="assets/js/script.js"></script>
</body>
</html>
Prima del tag di chiusura, abbiamo incluso una serie di librerie JavaScript. Questi sono il framework jQuery, il plugin jQuery Knob e le dipendenze per il Plugin jQuery File Upload.
L’elemento principale della pagina è il “div” form di caricamento. All’interno c’è il div #drop (che supporta il drag&drop) e una lista non ordinata. Questo elenco conterrà una voce li per ognuno dei file trasferiti.
L’elemento “input” in questo frammento di codice è nascosto tramite CSS. Il suo unico scopo è quello di inizializzare il plugin jQuery Knob, che genera come risultato una bella barra di progresso. Per utilizzarlo, basta passare in ingresso un paio di attributi “data-*” che ne modificano l’aspetto.
In seguito, durante l’upload, aggiorneremo il valore di questo input, il che causerà un aumento della percentuale di progresso.
Fase 2 – jQuery
Ci sono due modi in cui un visitatore può caricare i file in questo form:
- Trascinando i file sulla finestra (in tutti i browser tranne IE);
- Cliccando sul pulsante Sfoglia.
Quest’ultimo simulerà un click sul file di input nascosto, che poi mostrerà all’utente la finestra di sfoglia del sistema. Si noti che il file di input ha il set per i parametri multipli, che consentirà all’utente di selezionare più di un file in un colpo solo (i file saranno però caricati singolarmente).
La filosofia su cui si basa il plugin, è quella di inserire i file in una sorta di coda, e faremo in modo che i file caricati compaiano automaticamente nell’elenco che abbiamo scritto nella fase 1.
Ma bando alle ciance, ecco il codice JavaScript:
(function upl($) { // Inizializziamo la lista in cui inserire tutti i file caricati listone = $(' ul'); // Funzione per meglio formattare la grandezza di dati var formatSize = function (b) { if (typeof b !== 'number') { return ''; } if (b >= 1000000000) { return (b / 1000000000).toFixed(2) + ' GB'; } if (b >= 1000000) { return (b / 1000000).toFixed(2) + ' MB'; } return (b / 1000).toFixed(2) + ' KB'; } $('#drop a').on('click', function () { // Simula il click per mostrare la finestra di dialogo $(this).parent().find('input').click(); }); // Inizializza jQuery File Upload $('#form').fileupload({ // Designa a quale div assegnare la possibilita' di drag/drop dropZone: $('#drop'), // Permette o meno upload di piu' file sequentialUploads: true, // Chiamata quando viene aggiunto un file alla coda add: function (e, data) { // Creo l'input di jQuery Knob var knob = $('
'); // Aggiunge nome e peso del file knob .find('p') .text(data.files[0].name) .append('' + formatSize(data.files[0].size) + ''); // Aggiunge HTML all'elemento UL data.context = knob.appendTo(listone); // Inizializza il plugin Knob knob.find('input').knob(); // Invia il form automaticamente non appena il file viene aggiunto alla coda var jqXHR = data.submit(); }, progress: function (e, data) { // Calcola la percentuale di completamento dell'upload var progress = parseInt(data.loaded/data.total * 100, 10); // Aggiorna il campo nascosto e segnala i cambiamenti in modo // che il plugin Knob aggiorni il progresso data.context.find('input').val(progress).change(); }, // (Eventuale) Qualcosa e' andato storto fail: function (e, data) { }, // (Eventuale) Tutto e' andato a buon fine done: function (e, data) { } }); })(jQuery); // Preveniamo l'azione di default per gli eventi 'drop' e 'dragover' document.addEventListener('drop dragover', function (e) { e.preventDefault(); });
Come si può notare, ci sono alcune callback che vengono restituite dal Plugin jQuery File Upload ed alcune proprietà particolari. Analizziamo quelle che abbiamo appena usato:
dropZone – Questa proprietà contiene il selettore jQuery dell’elemento che agirà come destinazione dei risultati. Tutti i dati lì rilasciati si aggiungono alla coda.
add – Questa funzione di callback viene chiamata ogni volta che un file viene aggiunto alla coda. Al suo interno, creiamo il markup HTML che rappresenterà il file, lo aggiungiamo alla lista non ordinata e attiviamo il metodo data.submit(). Questo farà sì che il file aggiunto venga caricato direttamente senza aspettare.
progress – Questa callback viene eseguita dal plugin ogni 100ms (configurabili). Il secondo argomento (l’attributo di dati) contiene la dimensione del file e quanti byte sono stati trasferiti. Questo ci permette di calcolare una percentuale, e successivamente aggiornare l’elemento input nascosto, che a sua volta aggiorna lo stato del progresso.
fail – Questa funzione di callback viene eseguito se si verifica un problema con il codice PHP. Ciò significa probabilmente che upload.php non esiste o lancia un qualche tipo di errore (usa l’ispettore del browser per eseguire il debug di eventuali problemi qui).
Consulta l’elenco completo di tutte le opzioni di configurazione disponibili in questa pagina.
Fase 3 – Lo script PHP
Di base, con jQuery File Upload è disponibile anche con uno script PHP robusto per gestire il caricamento di file, ma in questo tutorial, ne costruiremo uno nostro molto più leggero:
<?php
// Una lista delle estensioni permesse
$permessi = array('png', 'jpg', 'gif','zip');
if ( isset($_FILES['upl']) && $_FILES['upl']['error'] == 0 )
{
// Prendiamo l'estensione del file
$ext = pathinfo($_FILES['upl']['name'], PATHINFO_EXTENSION);
// Se l'estensione non e' supportata, restituiamo un errore ed usciamo dalla routine
//
if ( !in_array(strtolower($ext), $permessi) )
{
// Bisogna passare un JSON a jQuery File Upload in modo che
// possa restituire la callback
echo '{"status": "error"}';
exit;
}
// Si crea il file nella cartella 'upload'
if ( move_uploaded_file($_FILES['upl']['tmp_name'], 'upload/'.$_FILES['upl']['name']) )
{
// Restuiamo 'success'
echo '{"status": "success"}';
exit;
}
}
// Bisogna passare un JSON a jQuery File Upload in modo che
// possa restituire la callback
echo '{"status": "error"}';
exit;
Gli upload dei file inviati dal plugin hanno la stessa valenza di una normale forma di caricamento – ed è quindi possibile accedere alle informazioni relative alle arrivi attraverso il ‘$ _FILES‘.
Come già detto, anche se l’utente è in grado di selezionare un gruppo di file, essi vengono caricati uno per uno. Questo rende ancora più facile da gestire con il nostro script PHP.
Attualmente, i file vengono semplicemente spostati nella cartella “upload“, ma è possibile estendere il tutto aggiungendo l’autenticazione o la creazione di record nel database.
Finito!
Qui è possibile scaricare il sorgente completo di tutto ciò spiegato.