Remove the FileList from several "input: file"

I have this DOM:

var id = 0; $('input:file#upload')[0].files[ id ] 

Get the first file at the 0th index. The file properties are listed and everything works, but ...

How to remove elements from DOM [object FileList] using JavaScript?

+5
source share
5 answers

I am afraid that you cannot directly delete objects from a FileList object . Just assign $('input:file#upload')[0].files Array , and then remove the elements from this array using splice or the method of your choice, and then use Array .

+9
source

Finally found a way! Before that, I knew that input.files would accept a FileList, but the only way to get it is with a drag event.

But now I know how to create my own list of files!

This works in Chrome (and maybe some others)

 const dt = new DataTransfer() dt.items.add(new File([], 'a.txt')) input.files = dt.files // This will remove the fist item when selecting many files input.onchange = () => { const dt = new DataTransfer() for (let file of input.files) if (file !== input.files[0]) dt.items.add(file) input.onchange = null // remove event listener input.files = dt.files // this will trigger a change event } 
 <input type="file" multiple id="input"> 

This works in Firefox.

 const cd = new ClipboardEvent("").clipboardData cd.items.add(new File(['a'], 'a.txt')) input.files = cd.files // This will remove the fist item when selecting many files input.onchange = () => { const dt = new DataTransfer() for (let file of input.files) if (file !== input.files[0]) dt.items.add(file) input.onchange = null // remove event listener input.files = dt.files // this will trigger a change event } 
 <input type="file" multiple id="input"> 

The point is that you need to iterate over each file in the input, add the ones you still want to save, and assign file.files with a new list of files.

+3
source

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); 
+1
source

No, we can make it removable. I implemented this and it works definitely.

First you need to initialize these variables

 var newImageObj = []; var ImageNo = 0; 

Then write this code when changing file input

 $("#exampleInputFileProduct").change(function () { var fileUpload = document.getElementById("exampleInputFileProduct"); //$("#mainImages").html(''); //$("#subImages").html(''); if (typeof (FileReader) != "undefined") { //Here Check File Extension var regex = /^([a-zA-Z0-9\s_\\.\-:])+(.jpg|.jpeg|.gif|.png)$/; for (var i = 0; i < fileUpload.files.length; i++) { var j = 0; var file = fileUpload.files[i]; var NewFile = fileUpload.files[i]; //Here Check File Size 1MB = 1000000 Bytes if (file.size < 2048000) { if (regex.test(file.name.toLowerCase())) { var reader = new FileReader(); reader.onload = function (e) { if ($("#mainImages").find(".item").attr("id") == "FirstSlider") { $("#mainImages").html(''); $("#subImages").html(''); $("#subImages").append("<div class='item active'></div>"); } if ($("#mainImages").find(".item").hasClass("active")) { $("#mainImages").append("<div class='item " + ImageNo + "_CClass\'><i class='fa fa-times customIcon' onclick='RemoveImage(\"" + ImageNo + "_CClass\",\"" + fileUpload.files[j].name.toLowerCase() + "\")'></i><img class='CImage' src='" + e.target.result + "' alt='' /></div>"); } else { $("#mainImages").append("<div class='item active " + ImageNo + "_CClass'><i class='fa fa-times customIcon' onclick='RemoveImage(\"" + ImageNo + "_CClass\",\"" + fileUpload.files[j].name.toLowerCase() + "\")'></i><img class='CImage' src='" + e.target.result + "' alt='' /></div>"); } //if ($("#subImages").find(".item").length == 0) { // $("#subImages").append("<div class='item active'></div>"); //} else { if (($("#subImages").find(".item").find("div").length / 5) >= $("#subImages").find(".item").length) { $("#subImages").append("<div class='item'></div>"); } //} var append = 0; $.each($("#subImages").find(".item"), function (p, pelement) { if (append == 0) { if ($(pelement).find("div").length != 5) { var newID = $(pelement).find("div").length; newID = newID; $(pelement).append("<div onclick='LoadImage(\"" + ImageNo + "_CClass\")' data-slide-to='" + newID + "' class='thumb " + ImageNo + "_CClass'> <img src='" + e.target.result + "' alt=''></div>"); append = append + 1; } } }) j = j + 1; ImageNo = ImageNo + 1; } newImageObj.push(file); reader.readAsDataURL(file); } } } } else { alert("This browser does not support HTML5 FileReader."); } }); 

Then finally these 2 functions will help to do the rest

 function LoadImage(objclass) { $("#mainImages").find(".item").removeClass("active"); $("#mainImages").find("." + objclass + "").addClass("active"); } function RemoveImage(objclass, ImageName) { $.each(newImageObj, function (e, element) { if ($(this)[0].name.toLowerCase().trim() == ImageName.trim()) { newImageObj.pop(this); } }); $("#mainImages").find("." + objclass + "").remove(); $("#subImages").find(".item").find("." + objclass + "").remove(); if ($("#mainImages").find(".item").length == 0) { $("#mainImages").append("<div class='item active'><i class='fa fa-times customIcon'></i><img class='CImage' src='/Content/img/DefaultProduct.gif' alt='' /></div>"); $("#subImages").append("<div class='item active'><div data-target='#carousel' data-slide-to='0' class='thumb'> <img src='/Content/img/DefaultProduct.gif' alt=''></div></div></div>"); } else { $("#mainImages").find(".item").removeClass("active"); $("#mainImages").find(".item:first-child").addClass("active"); $("#subImages").find(".item").removeClass("active"); $("#subImages").find(".item:first-child").addClass("active"); } } 

Finally, when you submit your form, than take the files from the array

0
source

The most practical way to remove a FileList object is to simply remove the file input itself from the DOM and add it again. This will remove all items from the file list.

I know that many will say that this is not an elegant solution, but it is very easy to implement, the best approach for most cases, and you can do what is important with the input file, validation!

Now you see that managing a FileList object difficult. If you really need to manipulate a single file element, read β€œ Downloading Multiple Files and Multiple Selection” (Part 2) from RAYMOND CAMDEN . I prefer to simply force the user to select the files again (if he did something stupid) and give him an error message. This will not make the user experience bad.

We remind you that the input file leads to a security vulnerability ( Vulnerability: unlimited file downloads ).

Since this post actually did not answer the question, I know that he will not get any points, but we will really consider the alternatives. For my case, when I implemented the deletion of a file object element, it did not make sense to continue loading after some file did not pass the test, even if some files were in order. In the end, the user will still have to open the input file and repeat the process. So in my case, this function only added complexity, and the specification did not have that much control for the input file.

The following is a validation example that deletes all FileList object on failure:

 function validateFormfile(inputTypeFile_id) { $(inputTypeFile_id).change((event) => { //check if files were select, if not, nothing is done if (event.target.files.length > 0) { let fileName; let totalsize = 0; let notvalidate = false; for (let i = 0; i < event.target.files.length; i++) { fileName = event.target.files[i].name; fileSize = event.target.files[i].size; if (fileName != undefined || fileName != "") { if (validate_fileExtension(fileName) === false) { notvalidate = true; let errorMessage = "File upload must be of 'audio', 'image', 'video', 'text', or 'pdf' format!"; //write you error function to show error to user //alertpanel(errorMessage); console.log(errorMessage); break; } totalsize += Number(event.target.files[i].size); console.log(fileName, fileSize, "bytes"); } } //check if file size is bigger than maxsize let maxsize = 10 * 1024 * 1024; //10Mb if (totalsize > maxsize && notvalidate === false) { notvalidate = true; let errorMessage = 'Upload files cannot exceed the maximum of ${maxsize} bytes.'; //write you error function to show error to user //alertpanel(errorMessage); console.log(errorMessage); } if (notvalidate) { //select the node where to append the input file let inputlabel = $(inputTypeFile_id).siblings().first(); //we delete the input file element to delete its FileList object content and re-append to the DOM $(inputTypeFile_id).remove(); let input_file = $('<input type="file" id="upload" name="upload" accept="application/pdf, text/plain, audio/*, video/*, image/*" multiple required>'); //append the input file after the selected inputlabel node inputlabel.after(input_file); //re init any event listener for the re-appended element validateFormfile(inputTypeFile_id); } } }); } function validate_fileExtension(fileName) { let image_extensions = new Array("bmp", "jpg", "jpeg", "jpe", "jfif", "png", "gif"); let text_extensions = new Array("txt", "pdf"); let video_extensions = new Array("avi", "mpeg", "mpg", "mp4", "mkv"); let audio_extensions = new Array("mp3", "acc", "wav", "ogg"); let allowed_extensions = image_extensions.concat(text_extensions, video_extensions, audio_extensions); // split function will split the fileName by dot(.), and pop function will pop the last element from the array which will give you the extension as well. If there will be no extension then it will return the fileName. let file_extension = fileName.split('.').pop().toLowerCase(); for (let i = 0; i <= allowed_extensions.length; i++) { if (allowed_extensions[i] == file_extension) { return true; // valid file extension } } return false; } //init event listener to input file $(document).ready( validateFormfile("#upload") ); 
 label, input { display: block; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <label for="upload">Choose File(s) (Max: 10Mb)</label> <input type="file" id="upload" name="upload" accept="application/pdf, text/plain, audio/*, video/*, image/*" multiple required> <br><small>text|pdf|audio|image|video</small> 

I hope this helps in some way.

0
source

Source: https://habr.com/ru/post/1484668/


All Articles