【问题标题】:Is it possible to update FileList?是否可以更新 FileList?
【发布时间】:2018-08-29 13:39:22
【问题描述】:

我有:

<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 仅包含上次选择操作中的项目,因此我需要使用我积累的 FileList 项目列表更新 f.files

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

但第二行给出:

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

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

附带问题:我认为 Javascript 使用动态类型。为什么这里会报错类型?

【问题讨论】:

  • 我找不到参考,但我强烈怀疑File 对象必须是与&lt;input&gt; 元素或拖放目标关联的活动FileList 的一部分.
  • 这里有人回答了类似的问题:stackoverflow.com/questions/38449440/…

标签: javascript


【解决方案1】:

您无法修改文件列表,但您可以使用 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,将文件复制到新的。

【讨论】:

  • DataTransfer() 不支持 iOS
  • 另外,.items on DataTransfer() 在 IE11 中不受支持
  • DataTransfer() 在 Safari 中也不支持。 Safari 越来越像 IE。
  • Mac 和 ios 上的 Safari 现在支持DataTransfer()!!! caniuse.com/mdn-api_datatransfer_datatransfer自2021年4月起使用
  • 感谢您的回答,它对我有用!
【解决方案2】:

就像你说的

未能在“HTMLInputElement”上设置“文件”属性:提供的值不是“文件列表”类型。

您只能使用 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)
&lt;input type="file" id="fileInput" multiple /&gt;

这样做会触发更改事件,因此您可能希望打开和关闭更改事件侦听器

【讨论】:

  • 附带说明,这不适用于 iOS Safari。我还没有解决。
  • 这在测试中不起作用,例如。节点抱怨ClipboardEvent 未定义。
  • @windmaomao 那么您可能使用的是没有全局 ClipboardEvent 的旧浏览器,在这种情况下您想要做的是首先检查 ClipboardEvent 是否存在,如果不存在则使用 DataTransfer。
  • 根据developer.apple.com/forums/thread/133001,“剪贴板访问需要用户交互”。
  • 对我来说,它使用fileInput.prop('files', new FileListItems(files))而不是fileInput.files = new FileListItems(files)工作
猜你喜欢
  • 2015-07-18
  • 1970-01-01
  • 1970-01-01
  • 2015-02-11
  • 2016-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-06-18
相关资源
最近更新 更多