如何从 FileList 中删除文件

IT技术 javascript html drag-and-drop filelist
2021-01-16 03:52:35

我正在使用 HTML5 构建一个拖放式上传 Web 应用程序,我将文件放到一个 div 上,当然还有获取 dataTransfer 对象,它给了我FileList

现在我想删除一些文件,但我不知道如何,或者是否有可能。

最好我只想从 FileList 中删除它们;我对他们没有用。但如果这是不可能的,我是否应该在与 FileList 交互的代码中写入检查?那看起来很麻烦。

6个回答

如果您只想删除几个选定的文件:您不能。您链接到文件 API 工作草案包含一个注释:

HTMLInputElement接口[HTML5]有一个只读 FileList 属性,[...]
[重点煤矿]

阅读了一些 HTML 5 工作草案,我遇到了Common inputelement APIs看来您可以通过将对象属性设置为空字符串来删除整个文件列表,例如:valueinput

document.getElementById('multifile').value = "";

顺便说一句,使用 Web 应用程序中的文件一文可能也很有趣。

length我认为只有 是只读的。我尝试使用拼接删除一个项目,它在 Chrome 中失败。
2021-03-14 03:52:35
@RobinBerjon Chrome 似乎忽略了 'readonly' 属性,而 FireFox 不允许写操作。不幸的是,您只操作FileList 的建议在 FireFox 中也不起作用。
2021-03-29 03:52:35
@streetlight如果站点所有者可以确定从用户的机器上传哪些文件,那将是一个巨大的安全漏洞。
2021-03-29 03:52:35
请注意,只读属性并不意味着您不能更改它指向的对象。您可以操作 FileList(如果可能的话),这只是意味着您不能为其分配新的 FileList。
2021-04-01 03:52:35
有什么办法可以添加吗?
2021-04-07 03:52:35

这个问题已经被标记为已回答,但我想分享一些可能有助于其他人使用 FileList 的信息。

将 FileList 视为数组会很方便,但 sort、shift、pop 和 slice 等方法不起作用。正如其他人所建议的那样,您可以将 FileList 复制到一个数组中。然而,不是使用循环,而是有一个简单的单行解决方案来处理这种转换。

 // fileDialog.files is a FileList 

 var fileBuffer=[];

 // append the file list to an array
 Array.prototype.push.apply( fileBuffer, fileDialog.files ); // <-- here

 // And now you may manipulated the result as required

 // shift an item off the array
 var file = fileBuffer.shift(0,1);  // <-- works as expected
 console.info( file.name + ", " + file.size + ", " + file.type );

 // sort files by size
 fileBuffer.sort(function(a,b) {
    return a.size > b.size ? 1 : a.size < b.size ? -1 : 0;
 });

在 FF、Chrome 和 IE10+ 中测试正常

Array.from(fileDialog.files) 更简单
2021-03-15 03:52:35
@Muhammad Umer - 谢谢,我同意它更简单,并且被列为替代答案。然而,这取决于必须支持哪些浏览器,以及它们是否需要 pollyfill 才能使用 Array.from()。参见:stackoverflow.com/a/36810954/943435
2021-03-17 03:52:35
你实际上是如何修改 FileList 的?将此新数组分配给输入fileDialog.files = fileBuffer
2021-03-19 03:52:35
@3zzy - 可以修改 FileList,但仅限于现代浏览器。有关详细信息,请参阅此 SO 问题:stackoverflow.com/a/47522812/943435
2021-03-22 03:52:35
是 shift() 还是 splice() ?我觉得应该是后者。
2021-03-28 03:52:35

如果您的目标是常绿浏览器(Chrome、Firefox、Edge,但也适用于 Safari 9+),或者您可以负担得起 polyfill,则可以使用Array.from()如下方法将 FileList 转换为数组

let fileArray = Array.from(fileList);

然后很容易File像处理任何其他数组一样处理s 数组。

我还没有尝试过,但这是第一个谷歌结果;) github.com/mathiasbynens/Array.from
2021-03-18 03:52:35
完美的!你知道IE支持怎么样?或者你可以分享一个 polyfill 的链接?
2021-03-24 03:52:35
它只会让你处理fileArraynot fileList
2021-04-10 03:52:35

由于 JavaScript FileList 是只读的,不能直接操作,

最佳方法

您将不得不遍历input.fileswhile 将其与index要删除的文件的进行比较同时,您将使用new DataTransfer()设置一个新的文件列表,不包括要从文件列表中删除的文件。

通过这种方法,input.files本身的值发生了变化。

removeFileFromFileList(index) {
  const dt = new DataTransfer()
  const input = document.getElementById('files')
  const { files } = input
  
  for (let i = 0; i < files.length; i++) {
    const file = files[i]
    if (index !== i)
      dt.items.add(file) // here you exclude the file. thus removing it.
  }
  
  input.files = dt.files // Assign the updates list
}

替代方法

另一种简单的方法是将 FileList 转换为数组,然后进行拼接。

但这种方法不会改变 input.files

const input = document.getElementById('files')
// as an array, u have more freedom to transform the file list using array functions.
const fileListArr = Array.from(input.files)
fileListArr.splice(index, 1) // here u remove the file
console.log(fileListArr)
@ct0 这就是为什么你应该反向循环。从返回到数组的开始。所以你永远不会弄乱索引。
2021-03-12 03:52:35
非常感谢您,但是请注意,除非您从列表末尾删除文件,否则在某些时候不会删除任何内容,因为每个循环都会重置索引,因此为了解决这个问题,最好使用此技巧geeksforgeeks.org/how-to-get-the-child-node-index-in-javascript
2021-04-01 03:52:35

由于我们在 HTML5 领域,这是我的解决方案。要点是将文件推送到 Array 而不是将它们留在 FileList 中,然后使用 XHR2,将文件推送到 FormData 对象。下面举例。

Node.prototype.replaceWith = function(node)
{
    this.parentNode.replaceChild(node, this);
};
if(window.File && window.FileList)
{
    var topicForm = document.getElementById("yourForm");
    topicForm.fileZone = document.getElementById("fileDropZoneElement");
    topicForm.fileZone.files = new Array();
    topicForm.fileZone.inputWindow = document.createElement("input");
    topicForm.fileZone.inputWindow.setAttribute("type", "file");
    topicForm.fileZone.inputWindow.setAttribute("multiple", "multiple");
    topicForm.onsubmit = function(event)
    {
        var request = new XMLHttpRequest();
        if(request.upload)
        {
            event.preventDefault();
            topicForm.ajax.value = "true";
            request.upload.onprogress = function(event)
            {
                var progress = event.loaded.toString() + " bytes transfered.";
                if(event.lengthComputable)
                progress = Math.round(event.loaded / event.total * 100).toString() + "%";
                topicForm.fileZone.innerHTML = progress.toString();
            };
            request.onload = function(event)
            {
                response = JSON.parse(request.responseText);
                // Handle the response here.
            };
            request.open(topicForm.method, topicForm.getAttribute("action"), true);
            var data = new FormData(topicForm);
            for(var i = 0, file; file = topicForm.fileZone.files[i]; i++)
                data.append("file" + i.toString(), file);
            request.send(data);
        }
    };
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("Drop files or click here."));
    var handleFiles = function(files)
    {
        for(var i = 0, file; file = files[i]; i++)
            topicForm.fileZone.files.push(file);
    };
    topicForm.fileZone.ondrop = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
        handleFiles(event.dataTransfer.files);
    };
    topicForm.fileZone.inputWindow.onchange = function(event)
    {
        handleFiles(topicForm.fileZone.inputWindow.files);
    };
    topicForm.fileZone.ondragover = function(event)
    {
        event.stopPropagation();
        event.preventDefault();
    };
    topicForm.fileZone.onclick = function()
    {
        topicForm.fileZone.inputWindow.focus();
        topicForm.fileZone.inputWindow.click();
    };
}
else
    topicForm.fileZone.firstChild.replaceWith(document.createTextNode("It's time to update your browser."));
ajax 是唯一的方法然后我猜?
2021-03-22 03:52:35