Upload dei file in HTML5
Nel corso di questo articolo sarà illustrato come, attraverso l’uso dell’A.P.I. File introdotta in html, ottenere tutta una serie di informazioni relative ai file selezionati prima che questi siano caricati su di un server remoto, in particolare si illustrerà come effettuare questa operazione per mezzo di richieste Ajax, detto questo nella prima dell’articolo sarà illustrato come reperire le singole informazioni, dopo di che si mostrerà come creare un meccanismo di preview per i file caricati ed infine sarà illustrata la procedura di uploading vera e proprio.
Estrazione delle informazioni dai file caricati
File Singolo
Vediamo come accedere alle infomrazioni realtive ad un file nel caso di selezione singole; il questo caso il codice html è molto semplice ed assume la forma seguente
<input type=”file” id=”fileinput” />
L’id è stato utilizzato per poter consentire di individuare lo specifico elemento all’interno della pagina html.
Quando un utente seleziona un file, è scatenato in automatico l’evento “change” questo ci consente di aggiungere un listener programmato per rispondere proprio a questa variazione di stato e che può essere definito nel modo seguente:
document.getElementById(‘fileinput’).addEventListener(‘change’, function() { function() { var file = this.files[0]; // si mostrano i vari dati tramite il sistema di log console.log(“nome :”+file.name); console.log(“dimensioni :”+file.size); console.log(“tipo :”+file.type); console.log(“data di ultima modifica :”+file.lastModified); },false);
Osservando il codice si rende immediatamente conto di quanto sia semplice utilizzare questa libreria, in pratica non fa altro che aggiungere la proprietà “files” all’elemento HTMLInputElement.
Un aspetto importante va sottolineato: “Le proprietà associate agli oggetti files non sono modificabili, posso quindi essere solo lette”.
Osservando il codice proposto si nota come il reperimento delle informazioni relative al file caricato sono state ottenute accedendo alla posizione 0 della colletion FileList.
File Multipli
In questa sezione mostreremo come gestire l’operazione di recupero dei dati relativi ad una selezione multipla, in questo caso li codice HTML presenta una formalizzazione simile alla seguente:
<input type=’file’ id=’fileInput’ multiple=”multiple” />
In questo caso per abilitare la selezione multipla è stato aggiungere la proprietà multiple, il valore =”multiple” può essere omesso in quanto la sua assenza viene interpretata come una abilitazione implicita alla selezione multipla questo significa che è possibile scrivere
<input type=”file” id=”fileInput” multiple />
In modo del tutto simile a come avviene con altre proprietà HTML come ad esempio la required. In questo caso il listener descritto nella sezione precedente viene modificato nel modo seguente:
document.getElementById(‘fileInput’).addEventListener(‘change’, function() { for(var i = 0; i <this.files.length; i++) { var file= this.files[i]; // si mostrano i vari dati tramite il sistema di log console.log(“nome :”+file.name); console.log(“dimensioni :”+file.size); console.log(“tipo :”+file.type); console.log(“data di ultima modifica :”+file.lastModified); },false);
Rispetto al codice precedente si nota la presenza del ciclo for, questo in particolare è utilizzato per scandire tutti gli elementi selezionati in particolare il loro numero è descritto dalla proprietà length, essendo il primo elemento in posizione 0 la condizione di uscita dal ciclo è stata definita facendo uso dell’operatore < e non <= il cui uso avrebbe implicato l’accesso ad un elemento non presente nel vettore; l’accesso all’elemento corrente avviene allo stesso modo di quanto descritto in precedenza solo che in questo caso in luogo dello 0 si è fatto uso dell’indice i che è utilizzato per indicare la posizione corrente all’interno del vettore, In alternativa al ciclo for si sarebbe potuto fare uso anche del ciclo foreach ossia:
document.getElementById(‘fileInput’).addEventListener(‘change’, function() { for(var i in this.files) { var file = this.files[i]; console.log(“nome :”+file.name); console.log(“dimensioni :”+file.size); console.log(“tipo :”+file.type); console.log(“data di ultima modifica :”+file.lastModified); } },false);
E’ oltremodo possibile rendere il comportamento del type file più selettivo, nel senso che è possibile inserire una opportuna regola di filtering con la quale si abilita la possibilità di accettare solo immagini, nello specifico il tag di input con questa ulteriore regola assumerebbe l’aspetto descritto di seguito:
<input type=”file” id=’fileInput’ multiple accept=”image/*” />
In questo caso si consente la selezione di qualunque tipo di file, se al contrario si volesse abilitare solo la selezione dei file PNG allora l’accept andrebbe riscritta nel modo seguente accept=”image/png”.
Creazione di una preview
In questa sezione descriveremo in che modo è possibile creare una preview basata sui file che sono stati selezionati attraverso l’elemento di input, partiamo immediatamente dal codice html
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Preview images</title> <!--Import Google Icon Font--> <link href="//fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <!-- Compiled and minified CSS --> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" > <style> #gallery .thumbnail{ float:left; margin:2px; } </style> </head> <body> <h2>Upload images ...</h2> <form action="#"> <input type="file" id="fileinput" multiple accept="image/*" /> </form> <div class="conntainer" id="gallery" ></div> <script type="text/javascript" src="//code.jquery.com/jquery-2.1.1.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <script src="gallery.js"></script> </body> </html>
In questa circostanza si è preferito dividere il codice html dal javascript in modo da rendere più agevole la comprensione del testo
function previewImage(file) { var galleryId = "gallery"; var gallery = document.getElementById(galleryId); var imageType = /image.*/; if (!file.type.match(imageType)) { throw "File Type must be an image"; } var thumb = document.createElement("div"); thumb.className="col-sm6 col-xs-6 col-md-3"; var link = document.createElement("a"); link.setAttribute('href','#'); link.classList.add('thumbnail'); var img = document.createElement("img"); img.file = file; link.appendChild(img); thumb.appendChild(link); gallery.appendChild(thumb); var reader = new FileReader(); reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img); reader.readAsDataURL(file); } var uploadfiles = document.querySelector('#fileinput'); uploadfiles.addEventListener('change', function () { var myFiles = this.files; for(var i=0; i<this.files.length; i++){ previewImage(myFiles[i]); } }, false);
Nel codice presentato di è fatto uso l’oggetto FileREader che permette la lettura aisncorno del contenuto di un file facendo uso del metodo readAsUrl; il metodo onload è chiamato dopo che il contenuto del file è stato letto, dopo di che il contenuto del file all’attributo src del immagine mediante l’istruzione aImg.src = e.target.result.
Salvataggio su server remoto
In questa ultima sezione del nostro articolo presenteremo in che modo, attraverso una richiesta AJAX, è possibile caricare su server remoto le immagini selezionate tramite il nostro elemento di input, per quel che concerne gli script per il salvataggio questi saranno realizzati usando PHP, partiamo quindi con il presentare il codice javascript necessario all’invio dei dati:
function uploadFile(file){ var url = "../server/index.php"; var xhr = new XMLHttpRequest(); var fd = new FormData(); xhr.open("POST", url, true); xhr.onreadystatechange = function() { if (xhr.readyState == 4 && xhr.status == 200) { // Every thing ok, file uploaded console.log(xhr.responseText); // handle response. } }; fd.append('uploaded_file', file); xhr.send(fd); }
Questa funzione crea una richiesta POST all’url indicata nel codice i riferimenti ai file sono associati alla chiave uploaded_file indicata come primo argomento della funzione append, si ricorda a questo proposito che i dati relativi ai file inviati non saranno reperibili attraverso il vettore $_POST, ma per mezzo del $_FILES nello specifico per recuperare il vettore con i dati relativi ai diversi file caricati la sintassi da utilizzare sarà $_FILES[‘uploade_file’]; a questo punto non dobbiamo fare altro che associare il codice appena indicato all’evento change associato all’input.
Il codice html ha una forma molto semplice ossia:
<input type=”file” id=”uploadedfiles” multiple/>
Il javascript per la gestione dell’evento sarà invece:
var uploadfiles = document.querySelector('#uploadfiles'); uploadfiles.addEventListener('change', function () { var files = this.files; for(var i=0; i<files.length; i++){ uploadFile(this.files[i]); // call the function to upload the file } }, false);
il codice php per contro avrà la forma seguente
if (isset($_FILES['upload_file'])) { if(move_uploaded_file($_FILES['upload_file']['tmp_name'], "datas/" . $_FILES['upload_file']['name'])){ echo $_FILES['upload_file']['name']. " OK"; } else { echo $_FILES['upload_file']['name']. " KO"; } exit; } else { echo "No files uploaded ..."; }
In questo caso il comportamento del javascript che si invierà un file alla volta non un unico invio al cui interno sono presenti tutti i file, questo evita eventuali problemi di congestione del canale di trasmissione dato che ogni invio potrà potenzialmente seguire un percorso differente.
Commenti