有可能设置.files的属性<input type="file">元件到FileList从例如一个不同的<input type="file">元件.files特性或DataTransfer.files属性。请参阅使.files可设置#2866,将文件上传到HTML表单并提交它之间会发生什么?。
.files
<input type="file">
FileList
DataTransfer.files
FileList对象具有Symbol.iterator一个我们可以用它来设置一个属性File对象,它是迭代的,但是.files .length仍然被设置为0和传递一个<form>具有<input type="file">集,其中.files是使用上述方法产生一组File具有对象.size集到0。
Symbol.iterator
File
.length
0
<form>
.size
如何将Fileat FileList和set设置.length为FileList文件集的数量,其中将文件设置为FormData()object的位置?
FormData()
const input = document.createElement("input"); const form = document.createElement("form"); const [...data] = [ new File(["a"], "a.txt") , new File(["b"], "b.txt") ]; input.type = "file"; input.name = "files"; input.multiple = true; // set `File` objects at `FileList` input.files[Symbol.iterator] = function*() { for (const file of data) { yield file }; }; form.appendChild(input); const fd = new FormData(form); for (const file of input.files) { console.log(file); // `File` objects set at `data` } for (const [key, prop] of fd) { // `"files"`, single `File` object having `lastModified` property // set to a time greater than last `File` object within `data` // at Chromium 61, only `"files"` at Firefox 57 console.log(key, prop); } console.log(input.files.length); // 0
编辑:
正如 OP 所证明的 那样,在他们的要旨中,实际上有一种方法可以…
该数据传递构造函数目前只有闪烁的支持,以及FF=62](https://bugzilla.mozilla.org/show_bug.cgi?id=1351193)),应该创建一个可变的文件清单(目前铬总是返回一个新的文件清单,但它其实并不重要,对我们来说),通过DataTransferItemList访问。
如果我没记错的话,这是目前唯一遵循规范的方法,但是Firefox在实现ClipboardEvent构造函数时存在一个错误,在该示例中,相同的DataTransferItemList设置为read /write模式,从而可以解决此问题。对于FF<62。我不确定我对这些规范的解释,但我认为通常无法正常访问该规范)。
因此, guest271314 发现在FileList上设置任意文件的方式如下:
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) dT.items.add(new File(['foo'], 'programmatically_created.txt')); inp.files = dT.files; <input type="file" id="inp">
这一发现导致了这项新的提议,即默认情况下使FileList对象可变,因为不再有没有理由不这样做。
上一个(过时的)答案
你不能 不能通过脚本修改FileList对象*。
您只能将输入的FileList交换到另一个FileList,但不能修改它。 (除了用清空input.value = null)。
input.value = null
而且,您既不能从头开始创建FileList ,也不能只创建不能创建的DataTransfer对象,而是input[type=file]将创建此类对象。
input[type=file]
为了向您展示即使将input[type=file]FileList 设置为另一输入的输入,也不会创建新的FileList:
var off = inp.cloneNode(); // an offscreen input inp.onchange = e => { console.log('is same before', inp.files === off.files); off.files = inp.files; // now 'off' does have the same FileList as 'inp' console.log('is same after', inp.files === off.files); console.log('offscreen input FileList', off.files); console.log('resetting the offscreen input'); off.value = null; console.log('offscreen input FileList', off.files); console.log('inscreen input FileList', inp.files); } <input type="file" id="inp">
哦,我差点忘了FormData部分,我真的不明白说的是事实…
因此,如果我一切正常,那么您只需要FormData.append():
FormData.append()
var fd = new FormData(); fd.append("files[]", new Blob(['a']), 'a.txt'); fd.append("files[]", new Blob(['b']), 'b.txt'); for(let pair of fd.entries()) { console.log(pair[0], pair[1]); }