Как сделать отображение определенной иконки для определенного файла в предварительном просмотре загруаемых файлов

У меня есть код, с помощью которого, я могу предварительно просмотреть несколько загруженных файлов:

let file_array = [];

function scrollBottom() {
  let element = document.querySelector('.chat-item-body');
  element.scrollTop = element.scrollHeight - element.clientHeight;
}

scrollBottom();

$("#chat-file").change(function() {
  let input_files = document.getElementById('chat-file').files;

  $.each(input_files, function(index, value) {
    file_array.push(value);
    $('.preview__container').append(`
            <div class="preview__content">
                <div class="img"><img src="/img/fileType.png" alt=""></div>
                <p>${value.name}</p>
                <i class="far fa-times-circle delete_file" data-id="${file_array.length - 1}"></i>
            </div>
            `);
  });
});

$(document.body).on('click', '.delete_file', function() {
  let file_id = $(this).data('id');
  delete file_array[file_id];
  $(this).parent().remove();
});
.preview__container {
  width: 100%;
  margin-top: 10px;
}

.preview__content {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  position: relative;
  margin: 7px 0px;
  max-width: 200px;
}

.preview__content .img {
  margin-right: 5px;
}

.preview__content .img img {
  max-width: 46px;
  max-height: 46px;
}

.delete_file {
  position: absolute;
  right: 10px;
  top: 0;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-item-body">
  <label class="label-file" for="chat-file">
    <i class="icon i-clip"></i>
    <input type="file" name="file[]" multiple="" id="chat-file" />
  </label>
  <div class="preview__container">
  </div>
</div>

Я сделал так, чтобы значок отображался для любого загруженного документа. Однако нельзя сделать так, чтобы для определённого документа была определённая иконка:

введите сюда описание изображения

Как это может быть сделано?


Ответы (1 шт):

Автор решения: UModeL

Если исходить из простоты, то алгоритм следующий:

  • Загружаем необходимые иконки на сайт, предварительно дав им названия соответствующие необходимым расширениям;
  • Создаём массив с таким же набором расширений (он будет нужен для атрибута accept, чтобы ограничить выбор заданным набором);
  • Получаем расширение из имени файла и подставляем его в атрибуте src.

const aFileExt = ["7z", "avi", "bmp", "dll", "doc", "exe", "gif", "html", "jpg", "ogg", "txt", "zip"];
let file_array = [];

function scrollBottom() {
  let element = document.querySelector('.chat-item-body');
  element.scrollTop = element.scrollHeight - element.clientHeight;
}
scrollBottom();

$('#chat-file')
  .change(function() {
    let input_files = document.getElementById('chat-file').files;
    $.each(input_files, function(index, value) {
      file_array.push(value);
      let aProp = value.name.split(/\.([^.]+?)$/gim);
      $('.preview__container')
        .append(
          `
        <div class="preview__content">
          <div class="img">
            <img src="https://icons.iconarchive.com/icons/pelfusion/flat-file-type/128/${aProp[1]}-icon.png" alt="">
          </div>
          <p>${aProp[0]}</p>
          <i class="far fa-times-circle delete_file" data-id="${file_array.length - 1}"></i>
        </div>
        `
        );
    });
  })
  .attr('accept', `.${aFileExt.join(',.')}`);

$(document.body).on('click', '.delete_file', function() {
  let file_id = $(this).data('id');
  delete file_array[file_id];
  $(this).parent().remove();
});
.preview__container {
  width: 100%;
  margin-top: 10px;
}

.preview__content {
  display: flex;
  align-items: center;
  position: relative;
  margin: 7px 0px;
  max-width: 200px;
}

.preview__content .img {
  margin-right: 5px;
}

.preview__content .img img {
  max-width: 46px;
  max-height: 46px;
}

.delete_file {
  position: absolute;
  right: 10px;
  top: 0;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-item-body">
  <label class="label-file" for="chat-file">
    <i class="icon i-clip"></i>
    <input type="file" name="file[]" multiple="" id="chat-file" />
  </label>
  <div class="preview__container">
  </div>
</div>

Можно сделать немного по-другому:

  • Подтягиваем изображение со спрайтами (линейное или матрицу) и, на основе размеров, вычисляем позиции иконок;
  • Создаём объект, где: ключи - это доступные расширения файлов, а значения - позиция иконки;
  • Вычленяем расширение из имени файла и передаём его функции, которая возвращает смещение background-position, исходя из позиции иконки.

const aFileIcon = {htm: 24, html: 24, css: 23, jpg: 0, txt: 5, wav: 11, mp3: 12, zip: 14, avi: 15};

function fFileIcon(sExt) {
  return `${2 - (aFileIcon[sExt] % 5) * 82}px ${2 - Math.floor(aFileIcon[sExt] / 5) * 81}px`;
}

let file_array = [];

function scrollBottom() {
  let element = document.querySelector('.chat-item-body');
  element.scrollTop = element.scrollHeight - element.clientHeight;
}
scrollBottom();

$('#chat-file')
  .change(function() {
    let input_files = document.getElementById('chat-file').files;
    $.each(input_files, function(index, value) {
      file_array.push(value);
      let aProp = value.name.split(/\.([^.]+?)$/gim);
      $('.preview__container')
        .append(
          `
        <div class="preview__content">
          <div class="img"></div><p>${aProp[0]}</p>
          <i class="far fa-times-circle delete_file" data-id="${file_array.length - 1}"></i>
        </div>
        `
        )
        .find('.preview__content:last-child .img')
        .css('background-position', `${fFileIcon(aProp[1])}`);
    });
  })
  .attr('accept', `.${Object.keys(aFileIcon).join(',.')}`);

$(document.body).on('click', '.delete_file', function() {
  let file_id = $(this).data('id');
  delete file_array[file_id];
  $(this).parent().remove();
});
.preview__container {
  width: 100%;
  margin-top: 10px;
}

.preview__content {
  display: flex;
  align-items: center;
  position: relative;
  margin: 7px 0px;
  max-width: 200px;
}

.preview__content .img {
  margin-right: 5px;
  min-width: 80px;
  height: 80px;
  overflow: hidden;
  background-image: url(https://i.stack.imgur.com/TsgGF.jpg);
  background-size: 400px 400px;
  background-position: 0 0;
}

.delete_file {
  position: absolute;
  right: 10px;
  top: 0;
  cursor: pointer;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-item-body">
  <label class="label-file" for="chat-file">
    <i class="icon i-clip"></i>
    <input type="file" name="file[]" multiple="" id="chat-file" />
  </label>
  <div class="preview__container">
  </div>
</div>


Необходимые расширения можно добавлять, следя за наличием необходимого изображения. Одновременно ключи (значения) в объекте (массиве) являются набором доступных для выбора расширений - если ключ в объекте отсутствует, то такие файлы просто не отобразятся в окне выбора, исключая ситуацию, когда ассоциированная иконка отсутствует.

Конечно, нужны более серьёзные проверки на стороне сервера, но это уже другой вопрос.

→ Ссылка