Comment définir les objets File et la propriété length à L'objet FileList où les fichiers sont aussi reflétés à L'objet FormData?
il est possible de définir .files
propriété de <input type="file">
élément à un FileList
de par exemple un <input type="file">
élément différent .files
propriété ou DataTransfer.files
propriété. Voir Marque .fichiers table des matières # 2866 , que se passe-t-il entre le téléchargement d'un fichier dans un formulaire HTML et sa soumission? .
FileList
objet a une propriété Symbol.iterator
que nous pouvons utiliser pour définir un File
objet ce qui est itérable, cependant le .files
.length
est toujours défini à 0
et passe un <form>
ayant <input type="file">
ensemble où le .files
est défini en utilisant l'approche ci-dessus donne un File
Objet ayant .size
mis à 0
.
comment définir le File
à FileList
et définir .length
de FileList
au nombre de fichiers définis, où les fichiers sont définis à FormData()
objet?
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
1 réponses
Edit:
prouvé par l'OP , dans l'un des leur gist , il est en fait un moyen de le faire...
le constructeur DataTransfer (actuellement seulement supporté par Blink, et FF > = 62 ), devrait créer une liste de fichiers mutable (chrome actuellement toujours retourner une nouvelle liste de fichiers, mais il n'a pas vraiment d'importance pour nous) , accessible via la DataTransferItemList.
si Je ne me trompe pas, c'est actuellement la seule façon specs-wise de le faire, mais Firefox a eu un bug dans leur mise en œuvre du constructeur ClipboardEvent , où la même DataTransferItemList était et mis sur le mode lire/écrire qui a permis un travail autour de FF < 62. Je ne suis pas sûr de mon interprétation des spécifications, mais je crois qu'il ne devrait pas être accessible normalement).
Donc la manière de guest271314 trouvés pour définir des fichiers arbitraires sur une liste de Fichiers est le suivant:
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">
cette découverte a conduit à cette nouvelle proposition de rendre les objets FileList mutables par défaut, car il n'y a plus de raison de ne pas le faire.
réponse précédente (périmée)
vous ne pouvez pas. Les objets FileList ne peuvent pas être modifiés par des scripts*.
vous ne pouvez échanger la liste D'une entrée que vers une autre liste de fichiers, mais vous ne pouvez pas la modifier*.
(*Sauf pour vider avec input.value = null
).
et vous ne pouvez pas non plus créer FileList à partir de zéro, seulement DataTransfer objets qui ne peuvent pas être créés non plus, et input[type=file]
va créer de tels objets.
pour vous montrer que même lors de la configuration d'une liste de fichiers input[type=file]
sur celle d'une autre entrée aucune nouvelle liste de fichiers n'est créée:
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">
Oh, Et j'ai presque oublié le FormData partie, que je n'ai pas vraiment compris à dire la vérité...
donc si je l'ai eu ok, Tout ce dont vous avez besoin est tout simplement 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]);
}