是否可以更新 FileList?

IT技术 javascript
2021-01-28 01:20:33

我有:

<input type="file" id="f" name="f" onchange="c()" multiple />

每次用户选择一个文件时,我都会通过将 的每个元素推f.files送到数组来构建所有选定文件的列表

var Files = [];
function c() {
  for (var i=0;i<this.files.length;i++) {
    Files.push(this.files[i]);
  };
}

在表单提交时,f.files只包含最后一个选择操作中的项目,所以我需要更新我积累f.filesFileList项目列表

const upload=document.getElementById("f");
upload.files = files;

但第二行给出:

未捕获的类型错误:无法在“HTMLInputElement”上设置“文件”属性:提供的值不是“FileList”类型。

我给它分配一个数组并不高兴。如何FileListFileList我之前收集元素列表中构造一个对象

附带问题:我认为 Javascript 使用动态类型。为什么它在这里抱怨错误的类型?

2个回答

您不能修改文件列表,但您可以使用 DataTransfer 对象创建一个新的文件列表,如果您愿意,可以将数据复制到其中以创建具有您想要进行的特定更改的副本。

let list = new DataTransfer();
let file = new File(["content"], "filename.jpg");
list.items.add(file);

let myFileList = list.files;

然后可以将其设置为 DOM 节点的文件属性:

fileInput.files = myFileList;

如果您愿意,可以遍历旧的 FileList,将文件复制到新的文件。

Mac 和 ios 上的 Safari 现在都支持DataTransfer()!!!caniuse.com/mdn-api_datatransfer_datatransfer 从 2021 年 4 月开始运行
2021-03-21 01:20:33
DataTransfer()Safari 中也不支持。Safari 正在变得像 IE。
2021-03-26 01:20:33
DataTransfer() 不支持 iOS
2021-04-01 01:20:33
Alsoo.itemsDataTransfer()不支持IE11
2021-04-13 01:20:33

就像你说的

无法在“HTMLInputElement”上设置“files”属性:提供的值不是“FileList”类型。

您只能使用 FileList 实例设置文件,不幸的是 FileList 不可构造或不可更改,但是有一种方法可以全面获取

/**
 * @params {File[]} files Array of files to add to the FileList
 * @return {FileList}
 */
function FileListItems (files) {
  var b = new ClipboardEvent("").clipboardData || new DataTransfer()
  for (var i = 0, len = files.length; i<len; i++) b.items.add(files[i])
  return b.files
}

var files = [
  new File(['content'], 'sample1.txt'),
  new File(['abc'], 'sample2.txt')
];


fileInput.files = new FileListItems(files)
console.log(fileInput.files)
<input type="file" id="fileInput" multiple />

这样做将触发更改事件,因此您可能需要打开和关闭更改事件侦听器

作为旁注,这不适用于 iOS Safari。我还没有解决。
2021-03-22 01:20:33
这不适用于测试,例如。节点抱怨ClipboardEvent未定义。
2021-03-24 01:20:33
@windmaomao 那么您可能使用的是没有全局 ClipboardEvent 的旧浏览器,在这种情况下您想要做的是首先检查 ClipboardEvent 是否存在,如果不存在,请改用 DataTransfer。
2021-03-29 01:20:33
根据developer.apple.com/forums/thread/133001 的说法,“剪贴板访问需要用户交互”。
2021-03-30 01:20:33
对我来说,它使用fileInput.prop('files', new FileListItems(files))而不是fileInput.files = new FileListItems(files)
2021-04-05 01:20:33