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]);
}