HTML5_FILE_API - Drag and Drop di file.

§ 1. L'oggetto DataTransfer durante il trascinamento di file

Nell'esempio precedente abbiamo visto come l'operazione di trascinamento generi un oggetto DataTranfer contenente informazioni sui dati trascinati. Vediamo cosa succede quando ad essere trascinati sono uno o più file selezionati mediante una finestra aperta tramite un elemento di input:

<input type="file" multiple>:

.

Non appena iniziamo a trascinare un file all'interno, o al di fuori della finestra di selezione, ci rendiamo conto che potremmo rilasciarlo dovunque:

In particolare il rilascio sulla pagina web stessa può provocare malfunzionamenti. Qui sono evitati tramite questo script:

var dropzoneId = 'dropzone';
window.addEventListener('dragenter', function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.dropEffect = "none";
    console.log('window.dragenter');
  }
},false);
window.addEventListener('dragover', function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.dropEffect = "none";
     console.log('window.dragover ');
 }
});
window.addEventListener('drop', function(e) {
  if (e.target.id != dropzoneId) {
    e.preventDefault();
    e.dataTransfer.dropEffect = "none";
    console.log('window.drop');
  }
});

In pratica sono disabilitati tutti gli effetti di trascinamento e rilascio su tutti gli elementi della finestra ad eccezione di quello con id=dropzone , l'area gialla sottostante.

dropzone - trascina i file qui

Il comportamento di default di un file trascinato sopra un elemento è quello di copiare il file nella locazione di destinazione. Per evitare questo comportamento ho utilizzato il seguente frammento di codice:

document.getElementById('dropzone').addEventListener('drop', Drop, false);
document.getElementById('dropzone').addEventListener('dragover', DragOver, false);

function DragOver(e){
         console.log("DragOver");
         e.stopPropagation();
         e.preventDefault(); 
         e.dataTransfer.dropEffect='link';
         return;
}
function Drop(e){
       console.log("Drop");
       e.stopPropagation();
       e.preventDefault(); 
       e.dataTransfer.dropEffect="none";
       ...
       ...
       e.stopPropagation();
       e.preventDefault(); 
       return;
}

Arrivati a questo punto possiamo utilizzare l'event listener "Drop" per vedere cosa c'è nell'oggetto DataTransfer.

Visualizzeremo tutte e properties dell'oggetto DataTransfer caricate selezionando i file, trascinandoli e rilasciandoli in dropzone:

Qui saranno visualizzate le properties dell'oggetto DataTransfer trascinato in dropzone.

E questo è il resto della funzione Drop:

function Drop(e){
       console.log("Drop");
       e.stopPropagation();
       e.preventDefault(); 
       e.dataTransfer.dropEffect="none";
       var prop = [];
       prop.push('<p>e.dataTransfer.types : ' + e.dataTransfer.types + '</p>');
       prop.push('<p>e.dataTransfer.effectAllowed : ' + e.dataTransfer.effectAllowed + '</p>');
       prop.push('<p>e.dataTransfer.dropEffect : ' + e.dataTransfer.dropEffect + '</p>');
       prop.push('<p>e.dataTransfer.files : ' + e.dataTransfer.files + '</p>');
       prop.push('<p>e.dataTransfer.files.length : ' + e.dataTransfer.files.length + '</p>');
       prop.push('<p>e.dataTransfer.items : ' + e.dataTransfer.items + '</p>');
       prop.push('<p>e.dataTransfer.items.length : ' + e.dataTransfer.items.length + '</p>');
       document.getElementById('text_output_1').innerHTML = '<p>Properties dell oggetto DataTransfer trascinato in dropzone:</p>' + prop.join('');
       e.stopPropagation();
       e.preventDefault(); 
       return;
}

§ 2. Esplorare gli oggetti File

La property files di DataTransfer contiene un array di oggetti File ognuno con le seguenti properties:

dropzone2 - trascina i file qui
Qui saranno visualizzate le properties degli oggetti File trascinati in dropzone2.

E questo è il codice :

document.getElementById('dropzone2').addEventListener('drop', Drop2, false);
document.getElementById('dropzone2').addEventListener('dragover', DragOver2, false);
function DragOver2(e){
         console.log("DragOver2");
         e.stopPropagation();
         e.preventDefault(); 
         e.dataTransfer.dropEffect='link';
         return;
}
function Drop2(e){
       console.log("Drop2");
       e.stopPropagation();
       e.preventDefault(); 
       e.dataTransfer.dropEffect="none";
       var prop = [];
       var dati = e.dataTransfer;
       if (dati.files.length>0){
          for (var i=0; i < dati.files.length; i++){
            prop.push('<p>file: ' + dati.files[i].name + '</p><ul>');
            prop.push('<li>type: ' + dati.files[i].type + '</li>');
            prop.push('<li>size: ' + dati.files[i].size + '</li>');
            prop.push('<li>lastModified: ' + dati.files[i].lastModified + '</li>');
            prop.push('<li>lastModifiedDate: ' + dati.files[i].lastModifiedDate + '</li>');
            prop.push('<li>webkitRelativePath: ' + dati.files[i].webkitRelativePath + '</li></ul>');
          }
            document.getElementById('text_output_2').innerHTML = '<p>Properties degli oggetti file</p>' + prop.join('');
          
       }else{
          alert("Nessun file selezionato");
       }
         e.stopPropagation();
         e.preventDefault(); 
       return;
}

§ 3. Utilizzo di FileReader

L'oggetto FileReader permette alle applicazioni web di leggere in maniera asincrona il contenuto di file (o di buffer di dati) memorizzati nel computer dell'utente, usando gli oggetti File o Blob per specificare i dati da leggere.

Gli oggetti file possono essere restituiti dagli oggetti FileList in seguito alla selezione di file operata mediante un elemento html input come visto sopra, oppure da un oggetto DataDransfer in seguito ad un operazione di drag and drop.

Costruttore

Per creare un oggetto FileReader usare la seguente sintassi:

var reader= new FileReader();

Eventi

Un oggetto FileReader può generare i seguenti eventi:

Properties

Un oggetto FileReader possiede le seguenti properties:

Metodi

Un oggetto FileReader possiede i seguenti metodi:

Esempi di utilizzo di FileReader

Utiliziamo questo metodo per

§ 3.1. Utilizzo del metodo readAsText

Limitiamo l'accesso del campo di input ai soli file elencati nell'attributo accept del campo di input.

<input type="file" accept=".txt,.css,.js,.dat,.html,.xml," >:

.

Il trascinamento e rilascio del file in "dropzone3" provocherà l'esecuzione del metodo readAsText del file, e la visualizzazione del suo contenuto nella zona sottostante.

dropzone3 - trascina il file qui
Qui sarà visualizzato il contentuto del file

Ecco il codice :

var reader = new FileReader();
reader.addEventListener('load', suEventoLoad);
var f;
document.getElementById('dropzone3').addEventListener('drop', Drop3);
document.getElementById('dropzone3').addEventListener('dragover', DragOver3);

function DragOver3(e){
         console.log("DragOver3");
         e.stopPropagation();
         e.preventDefault(); 
         e.dataTransfer.dropEffect='link';
}
function Drop3(e){
   console.log("Drop3");
   e.stopPropagation();
   e.preventDefault(); 
   e.dataTransfer.dropEffect="none";
   if (e.dataTransfer.files.length > 0 && (e.dataTransfer.types.includes("Files"))){
      alert ("Selezionato file: " + e.dataTransfer.files[0].name);
      f=e.dataTransfer.files[0];
      if (f.type.match('image.*')){
         reader.readAsDataURL(f);         
      }else if(f.type.match('text.*')){
         reader.readAsText(f,'UTF 8');
      }else{
         alert ("Questa applicazione non consente di visualizzare file di questo tipo: " + f.type);
      } 
   }else{
      alert("Nessun file selezionato");
   }         
   e.stopPropagation();
   e.preventDefault();   
}
function suEventoLoad(e){
   if (f.type.match('text.*')){
      document.getElementById('text_output_3').innerHTML = e.target.result.replace(/(?:\r\n|\r|\n)/g, '<br /'>');
   } else if(f.type.match('image.*')){
      //alert ("selezionata una immagine");
      document.getElementById('img_t').src = e.target.result;
   }
}

§ 3.2. Utilizzo del metodo readAsDataURL

Limitiamo l'accesso del campo di input ai soli file image.

<input type="file" accept=image/* >:

.

Il trascinamento e rilascio del file in "dropzone4" provocherà l'esecuzione del metodo readAsDataURL del file, e la sostituzione di "Image preview..."

dropzone4 - trascina il file qui
 Image preview....

Ecco il codice html con il quale è stata definita "Image preview...":

<img id="img_t"  alt=" Image preview...." src='' style="width:80%";>

E questo è il codice JavaScript

var reader = new FileReader();
reader.addEventListener('load', suEventoLoad);
var f;
document.getElementById('dropzone4').addEventListener('drop', Drop4);
document.getElementById('dropzone4').addEventListener('dragover', DragOver4);

function DragOver4(e){
         console.log("DragOver3");
         e.stopPropagation();
         e.preventDefault(); 
         e.dataTransfer.dropEffect='link';
}
function Drop4(e){
   console.log("Drop3");
   e.stopPropagation();
   e.preventDefault(); 
   e.dataTransfer.dropEffect="none";
   if (e.dataTransfer.files.length > 0 && (e.dataTransfer.types.includes("Files"))){
      f=e.dataTransfer.files[0];
      if (f.type.match('image.*')){
         reader.readAsDataURL(f);         
      }else if(f.type.match('text.*')){
         reader.readAsText(f,'UTF 8');
      }else{
         alert ("Questa applicazione non consente di visualizzare file di questo tipo: " + f.type);
      } 
   }else{
      alert("Nessun file selezionato");
   }         
   e.stopPropagation();
   e.preventDefault(); 
}
function suEventoLoad(e){
   if (f.type.match('text.*')){
      document.getElementById('text_output_3').innerHTML = e.target.result.replace(/(?:\r\n|\r|\n)/g, '<br /'>'');
   } else if(f.type.match('image.*')){
      //alert ("selezionata una immagine");
      document.getElementById('img_t').src = e.target.result;
   }
}