如何在FileList对象中设置File对象和length属性,其中文件也反映在FormData对象中? [英] How to set File objects and length property at FileList object where the files are also reflected at FormData object?

查看:123
本文介绍了如何在FileList对象中设置File对象和length属性,其中文件也反映在FormData对象中?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以将 .files 属性< input type =file> 元素设置为a FileList 例如来自不同的< input type =file> 元素 .files property或 DataTransfer.files property。请参阅使.files可设置#2866

It is possible to set .files property of <input type="file"> element to a FileList from for example a different <input type="file"> element .files property or DataTransfer.files property. See Make .files settable #2866, What happens between uploading a file to an HTML form and submitting it?.

FileList 对象有一个 Symbol.iterator 我们可以用来设置一个可迭代的 File 对象的属性,但 .files .length 仍然设置为 0 并传递< form> < input type =file> 设置使用上述方法设置 .files 的位置产生文件对象 .size 设置为 0

FileList object has a Symbol.iterator property which we can use to set a File object which is iterable, however the .files .length is still set to 0 and passing a <form> having <input type="file"> set where the .files is set using the above approach yields a File object having .size set to 0.

如何在 FileList 设置文件并设置 .length FileList 到设置的文件数,其中文件设置为 FormData() o bject?

How to set the File at FileList and set .length of FileList to the number of files set, where the files are set at FormData() object?

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 验证,在他们的要点,实际上有办法做到这一点......

As proven by OP, in one of their gist, there is actually a way to do it...

DataTransfer构造函数(目前仅受Blink支持,和FF> = 62 ),应该创建一个可变的FileList (chrome当前总是返回一个新的FileList,但它并不重要我们),可通过DataTransferItemList访问。

The DataTransfer constructor (currently only supported by Blink, and FF >= 62), should create a mutable FileList (chrome currently always return a new FileList, but it doesn't really matter for us), accessible through the DataTransferItemList.

如果我没弄错的话,这是目前唯一的规范方式,但Firefox的实施中有 bug ClipboardEvent构造函数,其中设置了相同的DataTransferItemList到读/写模式,它允许FF的解决方法< 62. 我不确定我对规格的解释,但我认为它不应该是正常的。)

If I'm not mistaken, this is currently the only specs-wise way to do it, but Firefox had a bug in their implementation of the ClipboardEvent constructor, where the same DataTransferItemList was and set to the mode read/write which allowed a workaround for FF < 62. I am not sure of my interpretation of the specs, but I believe it should not be accessible normally).

所以方式 guest271314 发现在FileList上设置任意文件如下:

So the way guest271314 found to set arbitrary files on a FileList is as follow:

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">

此发现导致此 new Proposal 默认情况下使FileList对象可变,因为没有必要再做它。

This discovery has lead to this new Proposal to make FileList objects mutable by default, since there is no point anymore to not do it.

你不能。脚本*不能修改FileList对象。

You can't. FileList objects cannot be modified by scripts*.

您只能将输入的FileList交换到其他FileList,但不能修改它*。

(*除了清空使用 input.value = null )。

You can only exchange the FileList of an input to an other FileList, but you can't modify it*.
(*Except for emptying with input.value = null).

你不能从头开始创建FileList,只能 DataTransfer 对象也无法创建,输入[type = file] 将创建此类对象。

And you can't either create FileList from scratch, only DataTransfer objects which cannot be created either, and input[type=file] will create such objects.

为了告诉你即使将输入[type = file] FileList设置为另一个输入,也不会创建新的FileList :

To show you that even when setting an input[type=file] FileList to an other input's one no new FileList is created:

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部分,我真的不明白说实话......

Oh And I almost forgot the FormData part, that I don't really understood to say the truth...

所以如果我把它弄好了,你只需要 FormData.append()

So if I got it ok, all you need is simply 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]); 
}

这篇关于如何在FileList对象中设置File对象和length属性,其中文件也反映在FormData对象中?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆