Html 从多个“输入:文件”中删除文件列表项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16943605/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove a FileList item from a multiple "input:file"
提问by
I have this DOM:
我有这个 DOM:
var id = 0;
$('input:file#upload')[0].files[ id ]
That get's the first file on the 0th index. File properties are listed and all works, but...
那就是第 0 个索引上的第一个文件。列出了文件属性并且一切正常,但是...
How do we remove items from the DOM's [object FileList]
with JavaScript?
我们如何[object FileList]
使用 JavaScript从 DOM 中删除项目?
采纳答案by Imran Latif
I' am afraid that you cannot delete objects from FileList object
directly. Just assign $('input:file#upload')[0].files
to an Array
and then remove items from that array using splice
or method of your choice and then use that Array
.
恐怕您无法FileList object
直接从中删除对象。只需分配$('input:file#upload')[0].files
给 anArray
然后使用splice
您选择的方法从该数组中删除项目,然后使用 that Array
。
回答by Endless
Finally found a way!
I knew before that input.files
would accept a FileList but the only way to get it was throught a drag and drop event.
终于找到方法了!我之前input.files
就知道会接受 FileList,但获得它的唯一方法是通过拖放事件。
But now i know how to construct a own FileList!
但是现在我知道如何构建自己的 FileList 了!
This works in chrome (and maybe some other)
这适用于 chrome(也许还有其他一些)
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
这适用于 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 thing is you need to loop over each file in the input, add those you still want to keep and assign the file.files with the new list of files.
问题是您需要遍历输入中的每个文件,添加您仍然想要保留的文件,并使用新的文件列表分配 file.files。
回答by MeVimalkumar
I have found very quick & short workaround for this. Tested in many popular browsers (Chrome, Firefox, Safari);
我找到了非常快速和简短的解决方法。在许多流行的浏览器(Chrome、Firefox、Safari)中测试;
First, you have to convert FileList to an Array
首先,您必须将 FileList 转换为数组
var newFileList = Array.from(event.target.files);
to delete the particular element use this
删除特定元素使用此
newFileList.splice(index,1);
回答by Volfegan
The most practical way to remove FileList object
is to just remove the file input itself from the DOM and re-append it again. This will remove all the items from the file list.
最实用的删除方法FileList object
是从 DOM 中删除文件输入本身,然后再次重新附加它。这将从文件列表中删除所有项目。
I know a lot of people will say this is not an elegant solution, but it very easy to implement, a better approach for most cases, and you can do what is important with the input file, validation!
我知道很多人会说这不是一个优雅的解决方案,但它很容易实现,在大多数情况下是一种更好的方法,并且您可以对输入文件执行重要的操作,验证!
By now you see that to control the FileList object
is hard. If you really need to manipulate an individual file item, read Multi-File Uploads and Multiple Selects (Part 2), by RAYMOND CAMDEN
. I prefer to just make the user select the files again (if he done goofy) and give him an error message of what went wrong. This will not make the user experience bad.
到现在为止,您会看到FileList object
很难控制。如果您确实需要操作单个文件项,请阅读RAYMOND CAMDEN 的 Multi-File Uploads and Multiple Selects(第 2 部分)
。我更喜欢让用户再次选择文件(如果他做傻事)并给他一条错误消息,告诉他出了什么问题。这不会使用户体验变差。
As a reminder, be aware that input file brings security weakness (Vulnerability: Unrestricted File Upload).
提醒一下,请注意输入文件会带来安全漏洞(漏洞:无限制文件上传)。
Since this post didn't really answer the question, I know it won't get any points, but really consider the alternatives. For my case when I was implementing deleting a file object item, it didn't make sense continuing the upload after some file didn't pass the validation, even if some files were ok. In the end, the user would still have to open the input file and redo the process. So, for my case, this feature was just adding complexity, and it was not in the specification this much control for an input file.
由于这篇文章并没有真正回答这个问题,我知道它不会得到任何分数,但真的要考虑替代方案。对于我实现删除文件对象项时的情况,即使某些文件没问题,在某些文件未通过验证后继续上传也没有意义。最后,用户仍然必须打开输入文件并重做该过程。因此,就我而言,此功能只是增加了复杂性,并且在规范中并没有对输入文件进行如此多的控制。
Bellow an example with validation that deletes all the FileList object
when fails:
下面是一个带有验证的示例,该示例删除所有FileList object
失败时:
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.
我希望这在某种程度上有所帮助。
回答by Rush.2707
No, We can make it removable. I implemented this and it works definitely.
不,我们可以把它拆下来。我实现了这个,它绝对有效。
First you need to initialize this variables
首先你需要初始化这个变量
var newImageObj = [];
var ImageNo = 0;
Then write this code on file input's change
然后在文件输入的更改上编写此代码
$("#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 at last this 2 functions will help to do the rest
然后最后这 2 个函数将帮助完成剩下的工作
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");
}
}
At last when you submit your form than take the files from the array
最后,当您提交表单时,而不是从数组中获取文件