如何从输入文件控件中删除一个特定的选定文件

时间:2013-09-27 21:31:32

标签: javascript jquery file-upload multifile

如何从输入文件控件中删除一个特定的选定文件?

我有一个输入文件控件,可以选择多个文件;但是,我想验证一个文件,如果它有一个错误的扩展名,那么我应该从文件控件本身删除该文件,是否可能?

我试过如下

<input type="file" name="fileToUpload" id="fileToUpload" multiple/>


<script> $("#fileToUpload")[0].files[0] </script>

下面是该对象的屏幕截图,但我无法对其进行修改

enter image description here

5 个答案:

答案 0 :(得分:38)

正如其他人所指出的那样,FileList是只读的。您可以通过将这些文件推送到单独的Array来解决此问题。然后,您可以使用精选的文件列表执行任何操作。如果将目标上传到服务器,则可以使用FileReader API。

以下是完全避免需要修改FileList的方法。 步骤进行:

  1. 添加普通文件输入更改事件侦听器
  2. 从更改事件循环遍历每个文件,过滤所需的验证
  3. 将有效文件推送到单独的数组
  4. 使用FileReader API在本地读取文件
  5. 将有效的已处理文件提交至服务器
  6. 事件处理程序和基本文件循环代码:

    var validatedFiles = [];
    $("#fileToUpload").on("change", function (event) {
      var files = event.originalEvent.target.files;
      files.forEach(function (file) {
        if (file.name.matches(/something.txt/)) {
          validatedFiles.push(file); // Simplest case
        } else { 
          /* do something else */
        }
      });
    });
    

    下面是一个更复杂的文件循环版本,它显示了如何使用FileReader API将文件加载到浏览器中,并可选择将其作为Base64编码的blob提交给服务器。

      files.forEach(function (file) {
        if (file.name.matches(/something.txt/)) { // You could also do more complicated validation after processing the file client side
          var reader = new FileReader();
          // Setup listener
          reader.onload = (function (processedFile) {
            return function (e) {
              var fileData = { name : processedFile.name, fileData : e.target.result };
    
              // Submit individual file to server
              $.post("/your/url/here", fileData);
    
              // or add to list to submit as group later
              validatedFiles.push(fileData);
            };
          })(file);
    
          // Process file
          reader.readAsDataURL(file);
        } else { 
          /* still do something else */
        }
      });
    

    关于使用FileReader API的注意事项。 Base64编码文件将使其大小增加约30%。如果这是不可接受的,你需要尝试其他的东西。

答案 1 :(得分:4)

我认为我也应该在这里添加我的评论(我在这里回答:JavaScript delete File from FileList to be uploaded

我找到了解决方法。这根本不需要AJAX请求,表单可以发送到服务器。基本上,您可以创建hiddentext输入,并将其value属性设置为处理所选文件后创建的base64字符串。

<input type=hidden value=${base64string} />

您可能会考虑创建多个输入文件而不是输入texthidden。这不起作用,因为我们无法为其赋值。

此方法将输入文件包含在发送到数据库的数据中,并忽略输入文件:

  • 在后端不考虑该字段;
  • 您可以在序列化表单之前将disabled属性设置为输入文件;
  • 在发送数据之前删除DOM元素。

如果要删除文件,只需获取元素的索引并从DOM中删除输入元素(文本或隐藏)。

<强>要求:

  • 您需要编写逻辑来转换base64中的文件,并在输入文件触发change事件时将所有文件存储在数组中。

<强>优点:

  • 这基本上会给你很多控件,你可以过滤,比较文件,检查文件大小,MIME类型等等。

答案 2 :(得分:0)

我知道这是一篇旧文章,但是我花了很长时间尝试解决此问题,所以我将发布解决方案。有一种方法可以用另一个fileList更新fileField元素的fileList,这可以通过DataTransfer完成:

let updateFileList = function (fileField, index) {
  let fileBuffer = Array.from(fileField.files);
  fileBuffer.splice(index, 1);

  /** Code from: https://stackoverflow.com/a/47172409/8145428 */
  const dT = new ClipboardEvent('').clipboardData || // Firefox < 62 workaround exploiting https://bugzilla.mozilla.org/show_bug.cgi?id=1422655
    new DataTransfer(); // specs compliant (as of March 2018 only Chrome)

  for (let file of fileBuffer) { dT.items.add(file); }
  fileField.files = dT.files;
}

上面的函数将fileField作为DOM对象,并删除要在fileField的fileList中删除的文件索引,并相应地更新传递的fileField。

希望这可以节省一些时间!

How to set File objects and length property at FileList object where the files are also reflected at FormData object?

答案 3 :(得分:0)

基于@liamthorne4 的回答,这里是上传、列出和从列表中删除元素的有效解决方案,在 Firefox 和 Chrome 上进行了测试:

HTML:

 <button onclick="uploadFile(event)">Upload files</button>
 <div id="listfiles" class="view_list"></div>
 <input class="hidden" type="file" id="input_file_id" onchange="fileList(event)" name="files[]" multiple>

JS:

    function uploadFile(evt) {
        evt.preventDefault();
        $('#input_file_id').click();
    }

    function fileList(e) {
        var files = $('#input_file_id').prop("files");
        var names = $.map(files, function(val) { return val.name; });
        for (n in names)    {
            $("#listfiles").append("<div id=preload_"+n+" title='"+names[n]+"'><p>"+names[n]+"</p><a  onclick=deleteFile("+n+")>Delete</a></div>");
        }
    }
    function deleteFile(index)  {
        filelistall = $('#input_file_id').prop("files");
        var fileBuffer=[];
        Array.prototype.push.apply( fileBuffer, filelistall );
        fileBuffer.splice(index, 1);
        const dT = new ClipboardEvent('').clipboardData || new DataTransfer(); 
        for (let file of fileBuffer) { dT.items.add(file); }
        filelistall = $('#input_file_id').prop("files",dT.files);
        $("#preload_"+index).remove()
    }

答案 4 :(得分:-9)

HTML

<input id="fileInput" name="fileInput" type="file" />
<input onclick="clearFileInput()" type="button" value="Clear" />

的javascript

    function clearFileInput(){
        var oldInput = document.getElementById("fileInput");

        var newInput = document.createElement("input");

        newInput.type = "file";
        newInput.id = oldInput.id;
        newInput.name = oldInput.name;
        newInput.className = oldInput.className;
        newInput.style.cssText = oldInput.style.cssText;
        // copy any other relevant attributes

        oldInput.parentNode.replaceChild(newInput, oldInput);
    }