webentwicklung-frage-antwort-db.com.de

Wie entferne ich eine Datei aus der Dateiliste?

Ich baue eine Drag-and-Drop-Upload-Webanwendung mithilfe von HTML5 auf, und ich lege die Dateien auf ein div und natürlich das dataTransfer-Objekt, was mir die FileList gibt.

Jetzt möchte ich einige Dateien entfernen, weiß aber nicht wie oder ob es überhaupt möglich ist. 

Vorzugsweise möchte ich sie einfach aus der Dateiliste löschen. Ich habe keine Verwendung für sie. Wenn dies nicht möglich ist, sollte ich stattdessen Überprüfungen in Code schreiben, der mit der Dateiliste interagiert? Das erscheint umständlich.

75
Heilemann

Wenn Sie nur einige der ausgewählten Dateien löschen möchten, können Sie dies nicht tun. Der File API Working Draft mit dem Sie verlinkt haben, enthält einen Hinweis:

Die HTMLInputElement-Schnittstelle [HTML5] hat eine readonlyFileList Attribut, […]
[Hervorhebung mein]

Beim Lesen eines kleinen HTML 5 Working Draft stieß ich auf die Common input-Element-APIs . Anscheinend können Sie die gesamte Dateiliste löschen, indem Sie die value -Eigenschaft des input-Objekts auf eine leere Zeichenfolge setzen, z.

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

Übrigens, der Artikel Dateien aus Webanwendungen verwenden könnte ebenfalls von Interesse sein.

93
Marcel Korpel

Diese Frage wurde bereits als beantwortet markiert, aber ich möchte einige Informationen mitteilen, die anderen bei der Verwendung von FileList helfen könnten.

Es wäre praktisch, eine FileList als Array zu behandeln, aber Methoden wie Sortieren, Shift, Pop und Slice funktionieren nicht. Wie von anderen vorgeschlagen, können Sie die Dateiliste in ein Array kopieren. Anstatt eine Schleife zu verwenden, gibt es jedoch eine einfache einzeilige Lösung für die Konvertierung.

 // 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 getestet in FF, Chrome und IE10 +

22
Roberto

Wenn Sie auf Evergreen-Browser (Chrome, Firefox, Edge, aber auch in Safari 9+) abzielen oder sich eine Polyfill leisten können, können Sie die FileList in ein Array umwandeln, indem Sie Array.from() folgendermaßen verwenden:

let fileArray = Array.from(fileList);

Dann ist es einfach, das Array von Files wie jedes andere Array zu behandeln.

14
adlr0

Da wir uns im HTML5-Bereich befinden, ist dies meine Lösung. Das Wichtigste ist, dass Sie die Dateien in ein Array verschieben, anstatt sie in einer Dateiliste zu belassen. Anschließend können Sie die Dateien mit XHR2 in ein FormData-Objekt verschieben. Beispiel unten.

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

Ich habe dafür eine sehr schnelle und kurze Lösung gefunden. In vielen gängigen Browsern getestet (Chrome, Firefox, Safari);

Zuerst müssen Sie FileList in ein Array konvertieren

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

um das bestimmte Element zu löschen, verwenden Sie dieses

newFileList.splice(index,1);
8
Vicky

Ich weiß, dass dies eine alte Frage ist, aber in Bezug auf dieses Problem eine hohe Platzierung in den Suchmaschinen hat.

eigenschaften im FileList Objekt können nicht gelöscht werden, aber zumindest in Firefox können sie geändert werden . Um dieses Problem zu beheben, war das Hinzufügen einer Eigenschaft IsValid=true zu den Dateien, die check und IsValid=false nicht bestanden haben.

dann durchlaufe ich die Liste, um sicherzustellen, dass nur die Eigenschaften mit IsValid=true zu FormData hinzugefügt werden.

4
A. Richards

Dies ist zwar temporär, aber ich hatte das gleiche Problem, das ich auf diese Weise gelöst habe. In meinem Fall habe ich die Dateien per XMLHttp-Anfrage hochgeladen, sodass ich die FileList-geklonten Daten über das Anhängen von formdata posten konnte. Die Funktionalität besteht darin, dass Sie mehrere Dateien beliebig oft ziehen und ablegen oder auswählen können (durch erneutes Auswählen der Dateien wird die geklonte Dateiliste nicht zurückgesetzt), jede gewünschte Datei aus der (geklonten) Dateiliste entfernt und über xmlhttprequest gesendet was auch immer dort übrig war. Das habe ich getan. Es ist mein erster Beitrag hier, also ist Code etwas unordentlich. Es tut uns leid. Ah, und ich musste jQuery anstelle von $ verwenden, wie in Joomla-Skript.

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

Nun die HTML und Stile dafür. Ich bin ein ziemlicher Neuling, aber all das hat tatsächlich für mich funktioniert und ich habe eine Weile gebraucht, um es herauszufinden.

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

Die Stile dafür. Ich musste einige davon markieren, um das Verhalten von Joomla außer Kraft zu setzen.

.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;
}

Ich hoffe das hilft.

1
Eric

Wenn Sie das Glück haben, eine Post-Anfrage mit den Dateien an die Datenbank zu senden, und Sie haben die Dateien, die Sie in Ihrem DOM senden möchten

sie können einfach überprüfen, ob die Datei in der Dateiliste in Ihrem DOM vorhanden ist. Wenn dies nicht der Fall ist, senden Sie dieses Element nicht einfach an de DB.

0
Neku80

Dank @Nicholas Anderson einfach und klar, hier ist Ihr Code angewendet und arbeitet an meinem Code mit 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 CODE

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

Es könnte einen eleganteren Weg geben, dies zu tun, aber hier ist meine Lösung. Mit Jquery

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

Grundsätzlich legen Sie den Wert der Eingabe fest. Klonen Sie es und setzen Sie den Klon anstelle des alten ein.

0