How to remove a file from FileList

I am creating a drag and drop web application using HTML5 and I drop the files on the div and of course retrieve the dataTransfer object that the FileList gives me.

Now I want to delete some of the files, but I do not know how, or if it is even possible.

I would just like to remove them from the FileList; They are useless to me. But if this is not possible, should you instead write in checks in code that interacts with the FileList? It seems cumbersome.

+82
javascript html5 drag-and-drop filelist
Jun 29 '10 at 20:20
source share
12 answers

If you want to delete only a few of the selected files, you cannot. The working draft API file you are referencing contains a note:

The HTMLInputElement [HTML5] interface has a readonly FileList attribute, [...]
[emphasis mine]

While reading a little working HTML 5 project, I came across General input element APIs . It seems you can delete the entire list of files by setting the value property of the input object to an empty string, for example:

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

By the way, the article Using files from web applications can also be of interest.

+98
Jul 01 '10 at 23:11
source share

This question has already been marked as an answer, but I would like to share some information that may help other users use FileList.

It would be convenient to consider FileList as an array, but methods such as sorting, shifting, pop and slice do not work. Like others, you can copy a FileList to an array. However, instead of using a loop, there is a simple one-line solution to handle this conversion.

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

Tested OK in FF, Chrome and IE10 +

+22
Nov 29 '15 at 1:31 on
source share

If you focus on evergreen browsers (Chrome, Firefox, Edge, but also works in Safari 9+), or you can afford polyfill, you can turn FileList into an array using Array.from() as follows:

 let fileArray = Array.from(fileList); 

Then it’s easy to process the File array like any other array.

+14
Aug 26 '16 at 9:37
source share

Since we are in the field of HTML5, this is my solution. The bottom line is that you push the files into the array, and do not leave them in the FileList, and then use XHR2, you click the files on the FormData object. An example is below.

 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 time to update your browser.")); 
+11
Sep 19
source share

I found a very quick and short workaround for this. Tested in many popular browsers (Chrome, Firefox, Safari);

First, you need to convert the FileList to an array

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

to delete a specific item use this

 newFileList.splice(index,1); 
+9
Nov 17 '17 at 10:55
source share

I know this is an old question, but he appreciates the search engines regarding this issue.

FileList object properties cannot be deleted, but at least on Firefox they can be changed . My workaround for this problem was to add the IsValid=true property to those files that passed the test, and IsValid=false to those that didn't.

then I just go through the list to make sure that only properties with IsValid=true added to FormData strong>.

+5
Jun 15 '15 at 3:48
source share

There may be a more elegant way to do this, but here is my solution. Using jquery

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

Basically you clear the input value. Clone it and put the clone instead of the old one.

+1
May 11 '16 at 19:43
source share

This is temporary, but I had the same problem that I solved in this way. In my case, I uploaded files using an XMLHttp request, so I could publish the cloned FileList data by adding form data. The functionality is that you can drag and drop or select multiple files as many times as you want (reselecting files will not reset the cloned list of files), delete any file from the list of (cloned) files and send everything that was left there through xmlhttprequest . This is what I did. This is my first post here, so the code is a bit dirty. I'm sorry. Ah, and I had to use jQuery instead of $, as it was in the Joomla script.

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

Now HTML and styles for this. I'm pretty new, but it all actually worked for me and took me some time to figure it out.

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

Styles for this. I should have noted some of them that are important in order to reject Joomla behavior.

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

Hope this helps.

+1
Mar 06 '18 at 2:46
source share

If you are lucky enough to send a mail request to the database with files, and you have files that you want to send to your DOM

you can simply check if the file is in the list of files in your DOM, and, of course, if you just do not send this item to the database.

0
Dec 30 '16 at 10:04
source share

Thanks @Nicholas Anderson, simple and straightforward, here is your code applied and working on my code using 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
Apr 12 '19 at 10:18
source share

You might want to create an array and use it instead of a read-only list of files.

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

After that, you can upload your list instead of your list. I am not sure about the context in which you work, but I work with the jquery plugin that I found, and what I needed to do was take the source of the plugin and put it on the page using <script> tags. Then, over the source, I added my array so that it could act as a global variable, and the plugin could reference it.

Then it's just a matter of replacing the links.

I think this will allow you to add drag and drop again if the built-in list is read-only, but how else could you get the dropped files to the list?

:))

-one
Mar 23 2018-11-11T00:
source share

I just change the type of text input and back to the file: D

-2
Jul 17 '18 at 13:18
source share



All Articles