50

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

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

我尝试如下

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


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

下面是对象的屏幕截图,但我无法修改它

在此处输入图像描述

4

5 回答 5

44

正如其他人指出的那样,FileList是只读的。您可以通过将这些文件推送到单独的文件中来解决此问题Array。然后,您可以使用该精选文件列表做任何您想做的事情。如果将它们上传到服务器是目标,您可以使用FileReaderAPI。

下面是一个完全避免需要修改FileList. 脚步:

  1. 添加普通文件输入更改事件监听器
  2. 从更改事件中循环遍历每个文件,过滤以进行所需的验证
  3. 将有效文件推送到单独的数组中
  4. 使用FileReaderAPI​​读取本地文件
  5. 向服务器提交有效的、已处理的文件

事件处理程序和基本文件循环代码:

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 */
    }
  });
});

下面是一个更复杂的文件循环版本,展示了如何使用FileReaderAPI 将文件加载到浏览器中,并可选择将其作为 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%。如果这不可接受,您将需要尝试其他方法。

于 2013-10-07T23:02:39.163 回答
5

我想我也应该在这里添加我的评论(我已经在这里回答了:JavaScript delete File from FileList to be upload

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

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

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

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

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

当您想删除文件时,只需获取元素的索引并从 DOM 中删除输入元素(文本或隐藏)。

要求:

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

优点:

  • 这基本上会给你很多控制,你可以过滤、比较文件、检查文件大小、MIME 类型等等。
于 2017-08-30T11:22:21.893 回答
4

我知道这是一篇旧帖子,但我花了很长时间试图解决这个问题,所以我会发布我的解决方案。有一种方法可以用另一个 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。

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

如何在 FileList 对象中设置文件对象和长度属性,其中文件也反映在 FormData 对象中?

于 2020-09-02T14:17:34.633 回答
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()
    }
于 2021-07-05T08:17:14.383 回答
-8

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);
    }
于 2014-09-27T11:52:41.140 回答