Pregunta

Estoy construyendo una aplicación web de arrastrar y soltar a la carga usando HTML5, y estoy dejando caer los archivos en un div y por supuesto de ir a buscar el objeto dataTransfer, lo que me da la FileList

Ahora quiero eliminar algunos de los archivos, pero no sé cómo, o si es aún posible.

Preferiblemente me gustaría simplemente borrarlos de la lista de archivos; No tengo ningún uso para ellos. Pero si eso no es posible, debería escribir en lugar de cheques en el código que interactúa con la lista de archivos? Eso parece engorroso.

¿Fue útil?

Solución

Si desea eliminar sólo algunos de los archivos seleccionados: no se puede. El File API Borrador de Trabajo que contiene vinculado a una nota:

  

La interfaz HTMLInputElement   [HTML5] tiene un sólo lectura FileList   atributo, [...]
  [Énfasis mío]

La lectura de un bit del Proyecto de Trabajo de HTML 5, me encontré con la API elemento input Común . Al parecer, se puede eliminar el toda lista de archivos mediante el establecimiento de la propiedad del objeto value input a una cadena vacía, como:

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

Por cierto, el artículo Uso de archivos de aplicaciones web también puede ser de interés.

Otros consejos

Esta pregunta ya ha sido contestada marcado, pero me gustaría compartir alguna información que pudiera ayudar a otros con el uso de FileList.

Sería conveniente para tratar una listaDeArchivos como una matriz, pero los métodos como género, turno, pop, y cortar en rodajas no hacer el trabajo. Como otros han sugerido, puede copiar la lista de archivos a una matriz. Sin embargo, en lugar de utilizar un bucle, hay una solución de línea simple de manejar esta conversión.

 // 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;
 });

Aceptar Probado en FF, Chrome y IE10 +

Si el idioma de hoja perenne navegadores (Chrome, Firefox, Edge, pero también funciona en Safari 9+) o puede permitirse un polyfill, puede activar la lista de archivos en una matriz mediante el uso de Array.from() como esto:

let fileArray = Array.from(fileList);

Entonces es fácil de manejar el conjunto de Files como cualquier otra matriz.

Ya que estamos en el reino de HTML5, esto es mi solución. Lo esencial es que se presiona los archivos a una matriz en lugar de dejarlos en una listaDeArchivos, a continuación, utilizando XHR2, empujar los archivos a un objeto FormData. Ejemplo a continuación.

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."));

he encontrado muy rápido y corto para esta solución. Probado en muchos navegadores más populares (Chrome, Firefox, Safari);

En primer lugar, usted tiene que convertir listaDeArchivos a una matriz

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

para eliminar el uso de este elemento en particular

newFileList.splice(index,1);

Sé que esto es una cuestión de edad, pero es alto ranking en los motores de búsqueda con respecto a este tema.

propiedades en el listaDeArchivos objeto no se puede eliminar, pero al menos en Firefox que se puede cambiar . Mi solucionar este problema fue la de añadir un IsValid=true propiedad a esos archivos que pasaron cheque y IsValid=false a los que no lo hicieron.

A continuación, acabo de bucle a través de la lista para asegurarse de que sólo las propiedades con IsValid=true se añaden a FormData .

Puede haber una manera más elegante de hacer esto, pero aquí está mi solución. Con jQuery

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

Básicamente cornamusa el valor de la entrada. Clon de él y poner el clon en el lugar de la antigua.

Este es extemporánea, pero no tenía el mismo problema que he resuelto de esta manera. En mi caso yo estaba subiendo los archivos a través de solicitud XMLHttp, así que fue capaz de enviar los datos a través FileList clonado anexar FormData. La funcionalidad es que puede arrastrar y soltar o seleccionar varios archivos tantas veces como desee (archivos de selección de nuevo, no se restablecerá la lista de archivos clonada), eliminar cualquier archivo que desee de la lista de archivos (clonado), y presentar a través xmlhttprequest lo que quedaba allí. Esto es lo que hice. Es mi primer post aquí lo que el código es un poco desordenado. Lo siento. Ah, y yo tenía que usar jQuery en lugar de $ como lo fue en la escritura de 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;
    }
};

Ahora el html y estilos para esto. Soy bastante novato, pero todo esto en realidad trabajaba para mí y me tomó un tiempo para averiguarlo.

<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>

Los estilos para ello. Tenía que marcar algunos de ellos! Importante para anular el comportamiento de 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;
}

Espero que esto ayude.

Si usted tiene la suerte de estar enviando una solicitud por correo postal a la base de datos con los archivos y tiene los archivos que desea enviar su DOM

simplemente se puede comprobar si el archivo en la lista de archivos está presente en el DOM, y por supuesto, si no es que simplemente no enviar ese elemento a de DB.

Gracias @Nicholas Anderson simple y directo, aquí está el código de aplicar y trabajar en mi código utilizando 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 código

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

Es posible que decida crear una matriz y el uso que en lugar de la lista de archivos de sólo lectura.

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

Después de ese punto hace su carga en contra de su lista en lugar de la incorporada en la lista. No estoy seguro del contexto en el que está trabajando, pero estoy trabajando con un plugin de jQuery que encontré y lo que tenía que hacer era tomar la fuente del plugin y lo puso en la página utilizando etiquetas <script>. Entonces encima de la fuente añadí mi matriz de modo que puede actuar como una variable global y el plugin podría hacer referencia a ella.

Entonces era sólo una cuestión de cambiar de las referencias.

creo que esto permitirá añadir también como arrastrar y soltar de nuevo, si el construido en la lista es de sólo lectura entonces, ¿cómo más se puede obtener los archivos deja caer en la lista?

:))

Me acaba de cambiar el tipo de entrada de texto y de nuevo al archivo: D

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top