Этот элемент ввода позволяет взять несколько изображений, например, если я выберу 2 изображения, я получу: FileList {0: файл, 1: файл, длина: 2}. Затем, если я снова выберу, например, 1 изображение, я получу другой список файлов: список файлов {0: файл, длина: 1}. Есть ли шанс поместить это новое изображение в первый FileList? А можно ли убрать образ FileList по его индексу? Заранее спасибо.
function handleFileSelect(evt) {
var files = evt.target.files; // FileList object
console.info(files);
for (var i = 0; i < files.length; i++) {
console.info(files[i]);
}
// Loop through the FileList and render image files as thumbnails.
for (var i = 0, f; f = files[i]; i++) {
if (!f.type.match('image.*')) {
continue;
}
let reader = new FileReader();
reader.onload = (function(theFile) {
return function(e) {
// Render thumbnail.
var span = document.createElement('span');
span.innerHTML = ['<img class = "thumb" src = "', e.target.result,
'" title = "', escape(theFile.name), '"/>'].join('');
document.getElementById('list').insertBefore(span, null);
};
})(f);
reader.readAsDataURL(f);
}
}
document.getElementById('files').addEventListener('change', handleFileSelect, false);.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}<input type = "file" id = "files" name = "files[]" multiple />
<output id = "list"></output>FileList не всегда 1. Я загрузил 3 элемента, и он показывает 3.
я загрузил изображение, как я вижу FileList в консоли



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы выбираете только один файл 3 раза.
Чтобы получить несколько файлов, вам нужно выбрать их одним вызовом из средства выбора файлов.
Это будет зависеть от ОС, но в моей macOS я могу сделать это, нажав клавишу cmd (вероятно, ctrl в других ОС), нажимая на элементы, которые я хочу выбрать.
Хороший! работает. Есть ли шанс получить FileList, выбрав файлы по отдельности? Спасибо
@sonEtLumiere вы всегда получаете FileList, даже если он содержит один файл. Есть способы добавлять файлы в input.files, но разве массива не будет достаточно для вашего случая?
Тогда массив и FormData - это путь.
Именно так вы можете добиться желаемого результата, используя FormData.
Вы можете изменить код, чтобы добиться желаемого внешнего вида и функциональности.
Вкратце, что делает следующий код:
FormDatafile-${index} field of FormData, созданное на шаге 1.FileReader для каждого FileFileReader считывает содержимое файла и возвращает данные: URL, представляющий данные файла в виде строки в кодировке base64.span и добавляет к нему элемент img с fileContent шага 5 как srcclick к span, поэтому, когда пользователь щелкает изображение, соответствующий файл будет удален из FormData шага 1, а span будет удален из DOMFormData будет отправлен на серверную часть в виде тела запроса с использованием Fetch API, когда пользователь нажмет кнопку submit files, используя функцию sendFiles в качестве обработчика кликов.вы можете увидеть список файлов, прикрепленных к FormData, с соответствующим именем поля формы и исходным именем файла под кнопкой Sunbmit как ul, сгенерированный с использованием функции listFiles
const formData = new FormData();
// to be used for files field names of FormData
let index = 0;
// for listing current files
const listFiles = () => {
const list = document.createElement("ul");
Array.from(formData.entries()).forEach((entry) => {
const item = document.createElement("li");
item.innerHTML = entry[0] + ": " + entry[1].name;
list.appendChild(item);
});
document.querySelector("#fileList").innerHTML = list.innerHTML;
};
// for sending files to the backend
const sendFiles = () => {
fetch("/upload/path", {
body: formData,
method: "POST",
})
.then((response) => response.json()) // If the response is in JSON format
.then((data) => {
console.info(data);
})
.catch((error) => {
console.error(error);
});
};
// for outputting fileReader output and file for FormData
// it needs to be async because of async nature of fileReader onload event so we can keep FormData and FileReader in sync using index
const readFile = (file) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = (event) => {
const theFile = event.target;
return resolve([file, theFile]);
};
fileReader.readAsDataURL(file);
});
};
const handleFileSelect = async (event) => {
var files = event.target.files;
for (const file of files) {
if (file.type.match("image.*")) {
const [fileData, theFile] = await readFile(file);
const id = `file-${index}`;
formData.append(id, fileData);
const span = document.createElement("span");
const img = document.createElement("img");
img.src = theFile.result;
img.alt = "Image thumb";
img.title = escape(fileData.name);
img.className = "thumb";
span.appendChild(img);
// for removing the thumbnail and its linked file from FormData
span.addEventListener("click", () => {
formData.delete(id);
// listing current files appended to FormData after removing this thumbnail
listFiles();
span.remove();
});
index++;
document.getElementById("list").insertBefore(span, null);
}
}
// list files after adding new file/files
listFiles();
};
document.getElementById("files").addEventListener("change", handleFileSelect, false);.thumb {
height: 75px;
border: 1px solid #000;
margin: 10px 5px 0 0;
}<input type = "file" id = "files" name = "files[]" multiple />
<br />
<h3>click on images to remove them</h3>
<output id = "list"></output>
<br /><br /><br />
<button onclick = "sendFiles()">submit Files</button>
<ul id = "fileList"></ul>пример Как загрузить файл с помощью Fetch для справки.
Похоже, вы утверждаете, что если вы
console.info(files.length), он всегда будет выводить1? Я не могу это воспроизвести. Если я выбираю несколько файлов, тоfiles.length— это количество файлов, которые я выбрал.