从多个“input:file”中删除FileList项

时间:2013-06-05 15:15:21

标签: javascript html5 input upload

我有这个DOM:

var id = 0;

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

这是第0个索引的第一个文件。列出了文件属性,但所有工作都有效,但是......

我们如何使用JavaScript从DOM [object FileList]中删除项目?

7 个答案:

答案 0 :(得分:10)

我担心您无法直接从FileList object删除对象。只需将$('input:file#upload')[0].files分配给Array,然后使用您选择的splice或方法从该数组中删除项目,然后使用Array

答案 1 :(得分:4)

终于找到了办法! 我之前知道input.files会接受一个FileList,但获得它的唯一方法是通过一个拖放事件。

但现在我知道如何构建自己的FileList!

这适用于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">
&#13;
&#13;
&#13;

这适用于Firefox

&#13;
&#13;
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
}
&#13;
<input type="file" multiple id="input">
&#13;
&#13;
&#13;

问题是你需要遍历输入中的每个文件,添加你仍想保留的文件,并为file.files分配新的文件列表。

答案 2 :(得分:2)

删除FileList object的最实用方法是从DOM中删除文件输入本身,然后再次重新添加。这将从文件列表中删除所有项目。

我知道很多人会说这不是一个很好的解决方案,但是它很容易实现,对于大多数情况来说是一个更好的方法,您可以对输入文件进行重要的验证!

现在,您已经发现控制FileList object很困难。如果您确实需要处理单个文件项,请阅读Multi-File Uploads and Multiple Selects (Part 2), by RAYMOND CAMDEN 。我更喜欢只是让用户再次选择文件(如果他做得很愚蠢),然后给他一条错误消息,指出出了什么问题。这不会使用户体验变差。

提醒一下,请注意输入文件带来安全漏洞(Vulnerability: Unrestricted File Upload)。

由于此帖子并未真正回答问题,我知道它不会有任何意义,但请真正考虑其他选择。就我而言,当我实现删除文件对象项时,即使某些文件没问题,在某些文件未通过验证后继续上传仍然没有意义。最后,用户仍然必须打开输入文件并重做该过程。因此,就我而言,此功能只是增加了复杂性,并且在规范中并没有对输入文件进行太多控制。

下面是一个带有验证的示例,该示例将在失败时删除所有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>

我希望这会有所帮助。

答案 3 :(得分:1)

我发现很快&amp;这个简短的解决方法。在许多流行的浏览器(Chrome,Firefox,Safari)中测试过;

首先,您必须将FileList转换为数组

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

删除特定元素使用此

newFileList.splice(index,1);

答案 4 :(得分: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");
            }
        }

然后最后这两个函数将有助于完成剩下的工作

1D

最后提交表单时,不是从数组中获取文件

答案 5 :(得分:0)

lst = []
for i in range(3):
    dct = {'x': i, 'y': (i+1), 'z': (i+2)}
    lst.append(dct)

print(lst)
# [{'x': 0, 'y': 1, 'z': 2}, {'x': 1, 'y': 2, 'z': 3}, {'x': 2, 'y': 3, 'z': 4}]

for dct in lst:
    print(dct['x'])
    print(dct['y'])
    print(dct['z'])
# 0
# 1
# 2
# 1
# 2
# 3
# 2
# 3
# 4
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;
}

答案 6 :(得分:0)

在通过ajax发送之前从fileList中删除文件。

1.创建 filesToUpload 列表 var filesToUpload = [];

  1. 将 FileId 和 File 本身添加到上面的数组中。(我们需要 FileId 到 通过与它们进行比较来找到已删除的文件 )
  2. 当点击删除图标时,会将删除的文件与 filesToUpload 并删除它。
  3. 当您通过 ajax 发送时,ajax 将采用 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);
            }
        });
    });
})()