Domanda

Sto costruendo un'applicazione web drag-and-drop-to-upload utilizzando HTML5, e sto cadere i file su un div e, naturalmente, andare a prendere l'oggetto dataTransfer, che mi dà la FileList

Ora voglio rimuovere alcuni dei file, ma non so come, o se è ancora possibile.

Preferibilmente vorrei cancellarli solo dalla FileList; Ho alcuna utilità per loro. Ma se questo non è possibile, dovrei invece scrivere in controlli nel codice che interagisce con il FileList? Che sembra ingombrante.

È stato utile?

Soluzione

Se si desidera eliminare diversi solo dei file selezionati: non si può. Il File API Working Draft si è collegato al contiene una nota:

  

L'interfaccia HTMLInputElement   [HTML5] ha una in sola lettura FileList   attributo, [...]
  [Corsivo mio]

La lettura di un po 'del progetto di HTML 5 di lavoro, mi sono imbattuto nel API elemento input Comune . Sembra è possibile eliminare il intero lista dei file impostando la proprietà value dell'oggetto input su una stringa vuota, come:

document.getElementById('multifile').value = "";

A proposito, l'articolo Utilizzo di file da applicazioni web potrebbe anche essere di interesse.

Altri suggerimenti

Questa domanda è già stata segnata una risposta, ma mi piacerebbe condividere alcune informazioni che potrebbero aiutare gli altri con l'utilizzo di FileList.

Sarebbe conveniente per il trattamento di un FileList come una matrice, ma i metodi come ordinamento, spostamento, pop, e la fetta non funzionano. Come altri hanno suggerito, è possibile copiare l'ElencoFile a un array. Tuttavia, invece di utilizzare un ciclo, c'è una soluzione semplice linea uno per gestire questa conversione.

 // fileDialog.files is a FileList 

 var fileBuffer=[];

 // append the file list to an array
 Array.prototype.push.apply( fileBuffer, fileDialog.files ); // <-- here

 // And now you may manipulated the result as required

 // shift an item off the array
 var file = fileBuffer.shift(0,1);  // <-- works as expected
 console.info( file.name + ", " + file.size + ", " + file.type );

 // sort files by size
 fileBuffer.sort(function(a,b) {
    return a.size > b.size ? 1 : a.size < b.size ? -1 : 0;
 });

OK Testato in FF, Chrome, e IE10 +

Se si prendono di mira sempreverdi browser (Chrome, Firefox, Riva, ma lavora anche in Safari 9+) o si può permettersi un polyfill, è possibile ruotare la FileList in un array utilizzando Array.from() in questo modo:

let fileArray = Array.from(fileList);

Poi è facile gestire la matrice di Files come qualsiasi altra matrice.

Dal momento che siamo nel regno HTML5, questa è la mia soluzione. Il succo è che si preme il file in un array invece di lasciarli in un FileList, quindi utilizzando XHR2, si preme il file a un oggetto formdata. Nell'esempio riportato di seguito.

Node.prototype.replaceWith = function(node)
{
    this.parentNode.replaceChild(node, this);
};
if(window.File && window.FileList)
{
    var topicForm = document.getElementById("yourForm");
    topicForm.fileZone = document.getElementById("fileDropZoneElement");
    topicForm.fileZone.files = new Array();
    topicForm.fileZone.inputWindow = document.createElement("input");
    topicForm.fileZone.inputWindow.setAttribute("type", "file");
    topicForm.fileZone.inputWindow.setAttribute("multiple", "multiple");
    topicForm.onsubmit = function(event)
    {
        var request = new XMLHttpRequest();
        if(request.upload)
        {
            event.preventDefault();
            topicForm.ajax.value = "true";
            request.upload.onprogress = function(event)
            {
                var progress = event.loaded.toString() + " bytes transfered.";
                if(event.lengthComputable)
                progress = Math.round(event.loaded / event.total * 100).toString() + "%";
                topicForm.fileZone.innerHTML = progress.toString();
            };
            request.onload = function(event)
            {
                response = JSON.parse(request.responseText);
                // Handle the response here.
            };
            request.open(topicForm.method, topicForm.getAttribute("action"), true);
            var data = new FormData(topicForm);
            for(var i = 0, file; file = topicForm.fileZone.files[i]; i++)
                data.append("file" + i.toString(), file);
            request.send(data);
        }
    };
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("Drop files or click here."));
    var handleFiles = function(files)
    {
        for(var i = 0, file; file = files[i]; i++)
            topicForm.fileZone.files.push(file);
    };
    topicForm.fileZone.ondrop = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
        handleFiles(event.dataTransfer.files);
    };
    topicForm.fileZone.inputWindow.onchange = function(event)
    {
        handleFiles(topicForm.fileZone.inputWindow.files);
    };
    topicForm.fileZone.ondragover = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
    };
    topicForm.fileZone.onclick = function()
    {
        topicForm.fileZone.inputWindow.focus();
        topicForm.fileZone.inputWindow.click();
    };
}
else
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("It's time to update your browser."));

ho trovato molto rapido e breve soluzione per questo. Testato in molti browser più diffusi (Chrome, Firefox, Safari);

In primo luogo, è necessario convertire FileList a una matrice

var newFileList = Array.from(event.target.files);

per eliminare l'uso particolare elemento di questo

newFileList.splice(index,1);

So che questa è una vecchia questione, ma è alto posizionamento sui motori di ricerca per quanto riguarda questo problema.

immobili a FileList oggetto non può essere eliminato, ma almeno su Firefox che può essere modificato . La mia soluzione questo problema è stato quello di aggiungere un IsValid=true proprietà per quei file che hanno superato di controllo e IsValid=false a quelli che non hanno.

poi ho appena scorrere l'elenco per assicurarsi che solo le proprietà con IsValid=true vengono aggiunti a formdata .

Ci potrebbe essere un più elegante modo per farlo, ma qui è la mia soluzione. Con Jquery

fileEle.value = "";
var parEle = $(fileEle).parent();
var newEle = $(fileEle).clone()
$(fileEle).remove();
parEle.append(newEle);

In pratica si tacchetta il valore dell'ingresso. Clone e mettere il clone al posto di quello vecchio.

Questa è estemporanea, ma ho avuto lo stesso problema che ho risolto in questo modo. Nel mio caso mi è stato il caricamento dei file tramite richiesta XMLHttp, così mi è stato in grado di pubblicare i dati FileList clonato attraverso accodamento formdata. Funzionalità è che si può trascinare e rilasciare o selezionare più file tutte le volte che si desidera (Selezione di file ancora una volta non si resetta il FileList clonato), rimuovere i file che si desidera dal (clonato) elenco dei file, e inviare via XMLHttpRequest ciò che è stato lasciato lì. Questo è quello che ho fatto. E 'il mio primo post qui in modo codice è un po' disordinato. Scusa. Ah, e ho dovuto usare jQuery invece di $ come era nello script di Joomla.

// some global variables
var clon = {};  // will be my FileList clone
var removedkeys = 0; // removed keys counter for later processing the request
var NextId = 0; // counter to add entries to the clone and not replace existing ones

jQuery(document).ready(function(){
    jQuery("#form input").change(function () {

    // making the clone
    var curFiles = this.files;
    // temporary object clone before copying info to the clone
    var temparr = jQuery.extend(true, {}, curFiles);
    // delete unnecessary FileList keys that were cloned
    delete temparr["length"];
    delete temparr["item"];

    if (Object.keys(clon).length === 0){
       jQuery.extend(true, clon, temparr);
    }else{
       var keysArr = Object.keys(clon);
       NextId = Math.max.apply(null, keysArr)+1; // FileList keys are numbers
       if (NextId < curFiles.length){ // a bug I found and had to solve for not replacing my temparr keys...
          NextId = curFiles.length;
       }
       for (var key in temparr) { // I have to rename new entries for not overwriting existing keys in clon
          if (temparr.hasOwnProperty(key)) {
             temparr[NextId] = temparr[key];
             delete temparr[key];
                // meter aca los cambios de id en los html tags con el nuevo NextId
                NextId++;
          }
       } 
       jQuery.extend(true, clon, temparr); // copy new entries to clon
    }

// modifying the html file list display

if (NextId === 0){
    jQuery("#filelist").html("");
    for(var i=0; i<curFiles.length; i++) {
        var f = curFiles[i];
        jQuery("#filelist").append("<p id=\"file"+i+"\" style=\'margin-bottom: 3px!important;\'>" + f.name + "<a style=\"float:right;cursor:pointer;\" onclick=\"BorrarFile("+i+")\">x</a></p>"); // the function BorrarFile will handle file deletion from the clone by file id
    }
}else{
    for(var i=0; i<curFiles.length; i++) {
        var f = curFiles[i];
        jQuery("#filelist").append("<p id=\"file"+(i+NextId-curFiles.length)+"\" style=\'margin-bottom: 3px!important;\'>" + f.name + "<a style=\"float:right;cursor:pointer;\" onclick=\"BorrarFile("+(i+NextId-curFiles.length)+")\">x</a></p>"); // yeap, i+NextId-curFiles.length actually gets it right
    }        
}
// update the total files count wherever you want
jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
    });
});

function BorrarFile(id){ // handling file deletion from clone
    jQuery("#file"+id).remove(); // remove the html filelist element
    delete clon[id]; // delete the entry
    removedkeys++; // add to removed keys counter
    if (Object.keys(clon).length === 0){
        jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
        jQuery("#fileToUpload").val(""); // I had to reset the form file input for my form check function before submission. Else it would send even though my clone was empty
    }else{
        jQuery("#form p").text(Object.keys(clon).length + " file(s) selected");
    }
}
// now my form check function

function check(){
    if( document.getElementById("fileToUpload").files.length == 0 ){
        alert("No file selected");
        return false;
    }else{
        var _validFileExtensions = [".pdf", ".PDF"]; // I wanted pdf files
        // retrieve input files
        var arrInputs = clon;

       // validating files
       for (var i = 0; i < Object.keys(arrInputs).length+removedkeys; i++) {
         if (typeof arrInputs[i]!="undefined"){
           var oInput = arrInputs[i];
           if (oInput.type == "application/pdf") {
               var sFileName = oInput.name;
               if (sFileName.length > 0) {
                   var blnValid = false;
                   for (var j = 0; j < _validFileExtensions.length; j++) {
                     var sCurExtension = _validFileExtensions[j];
                     if (sFileName.substr(sFileName.length - sCurExtension.length, sCurExtension.length).toLowerCase() == sCurExtension.toLowerCase()) {
                       blnValid = true;
                       break;
                     }
                   }
                  if (!blnValid) {
                    alert("Sorry, " + sFileName + " is invalid, allowed extensions are: " + _validFileExtensions.join(", "));
                    return false;
                  }
              }
           }else{
           alert("Sorry, " + arrInputs[0].name + " is invalid, allowed extensions are: " + _validFileExtensions.join(" or "));
           return false;
           }
         }
       }

    // proceed with the data appending and submission
    // here some hidden input values i had previously set. Now retrieving them for submission. My form wasn't actually even a form...
    var fecha = jQuery("#fecha").val();
    var vendor = jQuery("#vendor").val();
    var sku = jQuery("#sku").val();
    // create the formdata object
    var formData = new FormData();
    formData.append("fecha", fecha);
    formData.append("vendor", encodeURI(vendor));
    formData.append("sku", sku);
    // now appending the clone file data (finally!)
    var fila = clon; // i just did this because I had already written the following using the "fila" object, so I copy my clone again
    // the interesting part. As entries in my clone object aren't consecutive numbers I cannot iterate normally, so I came up with the following idea
    for (i = 0; i < Object.keys(fila).length+removedkeys; i++) { 
        if(typeof fila[i]!="undefined"){
            formData.append("fileToUpload[]", fila[i]); // VERY IMPORTANT the formdata key for the files HAS to be an array. It will be later retrieved as $_FILES['fileToUpload']['temp_name'][i]
        }
    }
    jQuery("#submitbtn").fadeOut("slow"); // remove the upload btn so it can't be used again
    jQuery("#drag").html(""); // clearing the output message element
    // start the request
    var xhttp = new XMLHttpRequest();
    xhttp.addEventListener("progress", function(e) {
            var done = e.position || e.loaded, total = e.totalSize || e.total;
        }, false);
        if ( xhttp.upload ) {
            xhttp.upload.onprogress = function(e) {
                var done = e.position || e.loaded, total = e.totalSize || e.total;
                var percent = done / total;
                jQuery("#drag").html(Math.round(percent * 100) + "%");
            };
        }
      xhttp.onreadystatechange = function() {
        if (this.readyState == 4 && this.status == 200) {
         var respuesta = this.responseText;
         jQuery("#drag").html(respuesta);
        }
      };
      xhttp.open("POST", "your_upload_handler.php", true);  
      xhttp.send(formData);
    return true;
    }
};

Ora l'html e stili per questo. Sono piuttosto un novizio ma tutto questo in realtà lavorato per me e mi ha portato un po 'per capirlo.

<div id="form" class="formpos">
<!--    Select the pdf to upload:-->
  <input type="file" name="fileToUpload[]" id="fileToUpload" accept="application/pdf" multiple>
  <div><p id="drag">Drop your files here or click to select them</p>
  </div>
  <button id="submitbtn" onclick="return check()" >Upload</button>
// these inputs are passed with different names on the formdata. Be aware of that
// I was echoing this, so that's why I use the single quote for php variables
  <input type="hidden" id="fecha" name="fecha_copy" value="'.$fecha.'" />
  <input type="hidden" id="vendor" name="vendorname" value="'.$vendor.'" />
  <input type="hidden" id="sku" name="sku" value="'.$sku.'"" />
</div>
<h1 style="width: 500px!important;margin:20px auto 0px!important;font-size:24px!important;">File list:</h1>
<div id="filelist" style="width: 500px!important;margin:10px auto 0px!important;">Nothing selected yet</div>

Gli stili per questo. Ho dovuto segnare alcuni di loro! Importante per ignorare il comportamento di Joomla.

.formpos{
  width: 500px;
  height: 200px;
  border: 4px dashed #999;
  margin: 30px auto 100px;
 }
.formpos  p{
  text-align: center!important;
  padding: 80px 30px 0px;
  color: #000;
}
.formpos  div{
  width: 100%!important;
  height: 100%!important;
  text-align: center!important;
  margin-bottom: 30px!important;
}
.formpos input{
  position: absolute!important;
  margin: 0!important;
  padding: 0!important;
  width: 500px!important;
  height: 200px!important;
  outline: none!important;
  opacity: 0!important;
}
.formpos button{
  margin: 0;
  color: #fff;
  background: #16a085;
  border: none;
  width: 508px;
  height: 35px;
  margin-left: -4px;
  border-radius: 4px;
  transition: all .2s ease;
  outline: none;
}
.formpos button:hover{
  background: #149174;
  color: #0C5645;
}
.formpos button:active{
  border:0;
}

Spero che questo aiuta.

Se si ha la fortuna di essere l'invio di una richiesta POST al database con i file e si hanno i file che si desidera inviare la tua DOM

si può semplicemente verificare se il file nella lista dei file è presente nel DOM, e, naturalmente, se è non solo non inviare quell'elemento a de DB.

Grazie @Nicholas Anderson semplice e diretto, qui è il codice applicato e di lavoro a mio codice utilizzando jQuery.

HTML.

<input class="rangelog btn border-aero" id="file_fr" name="file_fr[]" multiple type="file" placeholder="{$labels_helpfiles_placeholder_file}">
<span style="cursor: pointer; cursor: hand;" onclick="cleanInputs($('#file_fr'))"><i class="fa fa-trash"></i> Empty chosen files</span>

JS codice

   function cleanInputs(fileEle){
    $(fileEle).val("");
    var parEle = $(fileEle).parent();
    var newEle = $(fileEle).clone()
    $(fileEle).remove();
    $(parEle).prepend(newEle);
}

Si può decidere di creare un array e l'uso che, invece di lista_file sola lettura.

var myReadWriteList = new Array();
// user selects files later...
// then as soon as convenient... 
myReadWriteList = FileListReadOnly;

Dopo questo punto fare il vostro caricando contro la vostra lista invece del costruito in lista. Non sono sicuro del contesto in cui si sta lavorando, ma sto lavorando con un plugin jQuery che ho trovato e quello che ho dovuto fare è stato prendere sorgente del plugin e lo mise nella pagina utilizzando i tag <script>. Poi sopra la fonte ho aggiunto il mio allineamento in modo che possa agire come una variabile globale e il plugin potrebbe fare riferimento a esso.

Allora era solo una questione di sostituendo i riferimenti.

Credo che questo permetterebbe di aggiungere anche il drag & drop, come ancora una volta, se il costruito nel listino è di sola lettura, allora quale altro modo si potrebbe ottenere il file sceso in lista?

:))

Ho appena cambiare il tipo di ingresso al testo e al file: D

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top