Como definir objects de arquivo e propriedade de comprimento no object FileList, onde os arquivos também são refletidos no object FormData?

É possível definir a propriedade .files do elemento para uma FileList de, por exemplo, uma propriedade elemento .files ou da propriedade DataTransfer.files . Veja Make .files settable # 2866 , O que acontece entre carregar um arquivo em um formulário HTML e enviá-lo? .

FileList object FileList possui uma propriedade Symbol.iterator que podemos usar para definir um object File que seja iterável, no entanto, o .files .length ainda é definido como 0 e passando um com definido onde o .files é definido usando a abordagem acima gera um object File tendo .size definido como 0 .

Como definir o File em FileList e definir .length de FileList para o número de arquivos definidos, onde os arquivos são definidos no 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 

Editar:

Como comprovado pelo OP , em uma de suas teorias , há realmente uma maneira de fazer isso …

O construtor DataTransfer (atualmente suportado apenas por Blink e FF> = 62 ), deve criar um FileList mutável (o chrome atualmente sempre retorna um novo FileList, mas isso realmente não importa para nós) , acessível através do DataTransferItemList.

Se não estou enganado, esta é atualmente a única maneira de fazer isso, mas o Firefox tinha um bug na implementação do construtor ClipboardEvent , onde o mesmo DataTransferItemList estava e foi configurado para o modo de leitura / gravação que permitia uma solução alternativa. para FF <62. Não tenho certeza da minha interpretação das especificações, mas acredito que não deva ser acessível normalmente).

Portanto, a maneira como o guest271314 encontrou para definir arquivos arbitrários em um FileList é a seguinte:

 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;