Как удалить файл из списка файлов
Я создаю перетаскивание для загрузки веб-приложения с помощью HTML5, и я сбрасываю файлы на div и, конечно же, извлекаю объект dataTransfer, который дает мне FileList.
теперь я хочу удалить некоторые файлы, но я не знаю, как, или если это вообще возможно.
предпочтительно я хотел бы просто удалить их из списка файлов; у меня нет никакой пользы для них. Но если это невозможно, я должен вместо этого написать в чеки в коде, что взаимодействует с Список? Это кажется громоздким.
11 ответов:
если вы хотите удалить только несколько выбранных файлов: вы не можете. File API Working Draft вы связаны с содержит ноты:
The
HTMLInputElement
интерфейс [HTML5] имеет только для чтенияFileList
атрибут, [...]
[выделено мной]читая немного рабочего проекта HTML 5, я наткнулся на Common
input
Апис элемент. Похоже, вы можете удалить весь список, установивvalue
свойстваinput
объект пустой строки, например:document.getElementById('multifile').value = "";
кстати, статья использование файлов из веб-приложений также может представлять интерес.
на этот вопрос уже был отмечен ответ, но я хотел бы поделиться некоторой информацией, которая может помочь другим в использовании FileList.
было бы удобно рассматривать список файлов как массив, но такие методы, как sort, shift, pop и slice не работают. Как предлагали другие, вы можете скопировать список файлов в массив. Однако вместо использования цикла существует простое однострочное решение для обработки этого преобразования.
// 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; });
протестировано ОК в FF, Chrome и IE10+
Так как мы находимся в области HTML5, это мое решение. Суть заключается в том, что вы помещаете файлы в массив вместо того, чтобы оставлять их в списке файлов, а затем с помощью XHR2 вы помещаете файлы в объект FormData. Пример ниже.
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."));
Если вы ориентируетесь на вечнозеленые браузеры (Chrome, Firefox, Edge, но также работает в Safari 9+) или вы можете позволить себе полифилл, вы можете превратить список файлов в массив с помощью
Array.from()
такой:let fileArray = Array.from(fileList);
тогда это легко обрабатывать массив
File
как и любой другой массив.
Я нашел очень быстрый и короткий обходной путь для этого. Протестировано во многих популярных браузерах (Chrome, Firefox, Safari);
во-первых, вы должны преобразовать список в массив
var newFileList = Array.from(event.target.files);
для удаления конкретного элемента используйте это
newFileList.splice(index,1);
Я знаю, что это старый вопрос, но он занимает высокое место в поисковых системах в отношении этой проблемы.
свойства FileList объект не может быть удален, но по крайней мере на Firefox они могут быть изменены. Мое решение этой проблемы было добавить свойство
IsValid=true
к тем файлам, которые прошли проверку иIsValid=false
тем, кто этого не сделал.затем я просто перебираю список, чтобы убедиться, что только свойства с
IsValid=true
добавляются FormData.
это импровизация, но у меня была та же проблема, которую я решил таким образом. В моем случае я загружал файлы через запрос XMLHttp, поэтому я смог опубликовать клонированные данные FileList через добавление formdata. функциональность заключается в том, что вы можете перетаскивать или выбирать несколько файлов столько раз, сколько хотите (выбор файлов снова не приведет к сбросу клонированного списка файлов), удалять любой файл, который вы хотите из списка (клонированных) файлов, и отправлять через xmlhttprequest все, что там осталось. этот вот что я сделал. Это мой первый пост здесь, так что код немного грязный. Извиняюсь. Ах, и мне пришлось использовать jQuery вместо$, как это было в сценарии 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; } };
Теперь HTML и стили для этого. Я довольно новичок, но все это на самом деле сработало для меня и заняло некоторое время, чтобы понять это.
<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>
стили для этого. Я должен был отметить некоторые из них !важно, чтобы переопределить поведение для 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; }
Я надеюсь, что это помогает.
там может быть более элегантный способ сделать это, но вот мое решение. С Помощью Jquery
fileEle.value = ""; var parEle = $(fileEle).parent(); var newEle = $(fileEle).clone() $(fileEle).remove(); parEle.append(newEle);
в основном вы очищаете значение ввода. Клонируйте его и поместите клон вместо старого.
Если вам посчастливилось отправить запрос post в базу данных с файлами, и у вас есть файлы, которые вы хотите отправить в свой DOM
вы можете просто проверить, присутствует ли файл в списке файлов в вашем DOM, и, конечно же, если это не так, вы просто не отправляете этот элемент в de DB.
Вы можете создать массив и использовать его только для чтения список.
var myReadWriteList = new Array(); // user selects files later... // then as soon as convenient... myReadWriteList = FileListReadOnly;
после этого пункта сделать загрузку против вашего списка вместо встроенного списка. Я не уверен в контексте, в котором вы работаете, но я работаю с плагином jquery, который я нашел, и мне нужно было взять источник плагина и поместить его на страницу с помощью
<script>
теги. Затем над источником я добавил свой массив, чтобы он мог действовать как глобальная переменная, и плагин мог ссылаться оно.тогда это был просто вопрос замены ссылок.
Я думаю, что это позволит вам также добавить drag & drop как снова, если встроенный список доступен только для чтения, то как еще вы можете получить удаленные файлы в список?
:))