usar new formdata form files data create como javascript form-data fileapi filelist

new - javascript formdata jquery



¿Cómo establecer los objetos File y la propiedad de longitud en el objeto FileList donde los archivos también se reflejan en el objeto FormData? (1)

Es posible establecer la propiedad .files del elemento <input type="file"> en una FileList por ejemplo, desde una FileList diferente de <input type="file"> elemento .files o la propiedad DataTransfer.files . Consulte Make .files settable # 2866 , ¿Qué sucede entre cargar un archivo en un formulario HTML y enviarlo? .

FileList objeto FileList tiene una propiedad Symbol.iterator que podemos usar para establecer un objeto File que sea iterable, sin embargo, la .files .length todavía se establece en 0 y pasa un <form> tiene <input type="file"> establecido donde .files se establece usando el enfoque anterior produce un objeto File que tiene .size establecido en 0 .

¿Cómo establecer el File en FileList y establecer .length de FileList en el número de archivos establecidos, donde los archivos se establecen en el objeto 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 lo demostró OP , en uno de sus aspectos principales , en realidad hay una manera de hacerlo ...

El constructor DataTransfer (actualmente solo es compatible con Blink y FF> = 62 ), debe crear una FileList mutable (Chrome actualmente siempre devuelve una nueva FileList, pero realmente no nos importa) , accesible a través de DataTransferItemList.

Si no me equivoco, esta es actualmente la única forma de hacerlo en cuanto a especificaciones, pero Firefox tenía un error en su implementación del constructor ClipboardEvent , donde estaba el mismo DataTransferItemList y estaba configurado en el modo lectura / escritura que permitía una solución alternativa para FF <62. No estoy seguro de mi interpretación de las especificaciones, pero creo que no debería ser accesible normalmente).

Entonces, la forma en que guest271314 encontró para establecer archivos arbitrarios en una FileList es la siguiente:

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

Este descubrimiento ha llevado a esta nueva propuesta para hacer que los objetos FileList sean mutables de forma predeterminada, ya que ya no tiene sentido no hacerlo.

Respuesta anterior (obsoleta)

No puedes Los objetos FileList no pueden modificarse mediante scripts *.

Solo puede intercambiar la FileList de una entrada a otra FileList, pero no puede modificarla *.
(* Excepto para vaciar con input.value = null ).

Y tampoco puede crear FileList desde cero, solo los objetos DataTransfer que tampoco se pueden crear, y la input[type=file] creará dichos objetos.

Para mostrarle que incluso al configurar una input[type=file] FileList a otra entrada no se crea una nueva 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">

Ah, y casi me olvido de la parte FormData, que realmente no entendí para decir la verdad ...

Entonces, si lo tengo bien, todo lo que necesita es simplemente 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]); }