我有这个 DOM:
var id = 0;
$('input:file#upload')[0].files[ id ]
这是第 0 个索引上的第一个文件。列出了文件属性并且所有工作正常,但是...
我们如何[object FileList]
使用 JavaScript 从 DOM 中删除项目?
我有这个 DOM:
var id = 0;
$('input:file#upload')[0].files[ id ]
这是第 0 个索引上的第一个文件。列出了文件属性并且所有工作正常,但是...
我们如何[object FileList]
使用 JavaScript 从 DOM 中删除项目?
终于找到方法了!我之前知道input.files
会接受 FileList 但获得它的唯一方法是通过拖放事件。
但现在我知道如何构建自己的 FileList!
这适用于chrome(也许还有其他)
const dt = new DataTransfer()
dt.items.add(new File([], 'a.txt'))
input.files = dt.files
// This will remove the first 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">
这适用于 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">
问题是您需要遍历输入中的每个文件,添加您仍要保留的文件并为 file.files 分配新的文件列表。
恐怕您不能FileList object
直接从中删除对象。只需分配$('input:file#upload')[0].files
给 anArray
然后使用您选择的方法从该数组中删除项目,splice
然后使用 that Array
。
我为此找到了非常快速且简短的解决方法。在许多流行的浏览器(Chrome、Firefox、Safari)中测试;
首先,您必须将 FileList 转换为 Array
var newFileList = Array.from(event.target.files);
要删除特定元素,请使用此
newFileList.splice(index,1);
最实用的删除方法FileList object
是从 DOM 中删除文件输入本身并重新附加它。这将从文件列表中删除所有项目。
我知道很多人会说这不是一个优雅的解决方案,但它很容易实现,在大多数情况下是一种更好的方法,而且你可以对输入文件做重要的事情,验证!
到现在为止,你看到控制FileList object
是困难的。如果您确实需要操作单个文件项,请阅读RAYMOND CAMDEN 的 Multi-File Uploads and Multiple Selects (Part 2)
。我更喜欢让用户再次选择文件(如果他做错了)并给他一个错误消息,说明出了什么问题。这不会使用户体验变差。
提醒一下,请注意输入文件会带来安全漏洞(漏洞:不受限制的文件上传)。
由于这篇文章并没有真正回答这个问题,我知道它不会得到任何分数,但真正考虑替代方案。对于我在实施删除文件对象项时的情况,即使某些文件没问题,在某些文件未通过验证后继续上传也没有意义。最后,用户仍然必须打开输入文件并重做该过程。所以,就我而言,这个特性只是增加了复杂性,规范中并没有对输入文件进行如此多的控制。
下面是一个带有验证的示例,该示例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>
我希望这在某种程度上有所帮助。
由于您不能直接更改fileList
对象,因此您可以实例化一个新DataTransfer
对象并迭代地将所需的附加文件复制到它。然后将其分配给输入的 files 属性。
function removeFile(index){
var attachments = document.getElementById("attachment").files; // <-- reference your file input here
var fileBuffer = new DataTransfer();
// append the file list to an array iteratively
for (let i = 0; i < attachments.length; i++) {
// Exclude file in specified index
if (index !== i)
fileBuffer.items.add(attachments[i]);
}
// Assign buffer to file input
document.getElementById("attachment").files = fileBuffer.files; // <-- according to your file input reference
}
PS:我尝试使用DataTransferObject
.items.remove(index) 方法,但由于某种原因它清除了整个 fileList 数组。这就是我使用 for 循环的原因。
不,我们可以将其拆下。我实现了这一点,它确实有效。
首先你需要初始化这个变量
var newImageObj = [];
var ImageNo = 0;
然后在文件输入的变化上写下这段代码
$("#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.");
}
});
然后最后这两个功能将帮助完成其余的工作
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");
}
}
最后,当您提交表单而不是从数组中获取文件时
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>
在通过 ajax 发送之前从 fileList 中删除文件。
1.创建文件上传列表 var filesToUpload = [];
//Upload multi files and removable from files when user removed file ...
(function () {
var filesToUpload = [];
var fileIdCounter = 0;
var fileIdCounterOnload = 0;
$('#up').change(function (evt) {
for (var i = 0; i < evt.target.files.length; i++) {
fileIdCounter++;
var file = evt.target.files[i];
var fileId = "file" + fileIdCounter;
filesToUpload.push({
id: fileId,
file: file
});
var reader = new FileReader();
reader.onload = function (evt) {
fileIdCounterOnload++;
var fileIdOnload = "file" + fileIdCounterOnload;
$("<li class=\"pip\" data-fileid=\"" + fileIdOnload + "\">" +
"<img class=\"imageThumb\" src=\"" + evt.target.result + "\" title=\" \"/>" +
"<i class=\"icon-remove-circle remove removeFile\" ></i> " +
"</li>").insertAfter(".list");
$(".remove").click(function () {
var fileId = $(this).parent(".pip").data("fileid");
// loop through the files array and check if the name of that file matches FileName
// and get the index of the match
for (var i = 0; i < filesToUpload.length; ++i) {//here will start compare them
if (filesToUpload[i].id === fileId) {
filesToUpload.splice(i, 1);// delete a file from list.
}
}
$(this).parent(".pip").remove();// remove file from view .
});
};
reader.readAsDataURL(file); // convert to base64 string
};
//reset the input to null - nice little chrome bug!
evt.target.value = null;
});
$(".btn").click(function (e) {
e.preventDefault();
var formData = new FormData();
for (var i = 0, len = filesToUpload.length; i < len; i++) {
formData.append("files", filesToUpload[i].file);
}
$.ajax({
url: "/home/index2",
data: formData,
processData: false,
contentType: false,
type: "POST",
success: function (data) {
alert("DONE");
filesToUpload = [];
fileIdCounter = 0;
fileIdCounterOnload = 0;
},
error: function (data) {
alert("ERROR - " + data.responseText);
}
});
});
})()