Список файлов, отправка новых файлов изображений, доступ/удаление по индексу

Этот элемент ввода позволяет взять несколько изображений, например, если я выберу 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>

Похоже, вы утверждаете, что если вы console.info(files.length), он всегда будет выводить 1? Я не могу это воспроизвести. Если я выбираю несколько файлов, то files.length — это количество файлов, которые я выбрал.

Wyck 19.12.2020 02:56

FileList не всегда 1. Я загрузил 3 элемента, и он показывает 3.

Sifat Haque 19.12.2020 02:58

я загрузил изображение, как я вижу FileList в консоли

sonEtLumiere 19.12.2020 03:39
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
1
3
1 607
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы выбираете только один файл 3 раза.

Чтобы получить несколько файлов, вам нужно выбрать их одним вызовом из средства выбора файлов.
Это будет зависеть от ОС, но в моей macOS я могу сделать это, нажав клавишу cmd (вероятно, ctrl в других ОС), нажимая на элементы, которые я хочу выбрать.

Хороший! работает. Есть ли шанс получить FileList, выбрав файлы по отдельности? Спасибо

sonEtLumiere 19.12.2020 06:27

@sonEtLumiere вы всегда получаете FileList, даже если он содержит один файл. Есть способы добавлять файлы в input.files, но разве массива не будет достаточно для вашего случая?

Kaiido 19.12.2020 06:51

Тогда массив и FormData - это путь.

Kaiido 19.12.2020 08:30
Ответ принят как подходящий

Именно так вы можете добиться желаемого результата, используя FormData.

Вы можете изменить код, чтобы добиться желаемого внешнего вида и функциональности.

Вкратце, что делает следующий код:

  1. Создает новый экземпляр FormData
  2. Принимает файлы из файлового ввода
  3. Добавляет файл в поле с именем file-${index} field of FormData, созданное на шаге 1.
  4. Создает экземпляр FileReader для каждого File
  5. FileReader считывает содержимое файла и возвращает данные: URL, представляющий данные файла в виде строки в кодировке base64.
  6. Создает элемент span и добавляет к нему элемент img с fileContent шага 5 как src
  7. Прикрепляет прослушиватель click к span, поэтому, когда пользователь щелкает изображение, соответствующий файл будет удален из FormData шага 1, а span будет удален из DOM
  8. FormData будет отправлен на серверную часть в виде тела запроса с использованием 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 для справки.

Другие вопросы по теме