Отслеживайте папку изображений, чтобы получить живую локальную галерею html/javascript

Мне нужно получить галерею живых изображений на основе постоянно отслеживаемой папки. Он будет работать на моем локальном компьютере. Вот как это должно работать:

  • Если появляется файл изображения, он автоматически добавляется в галерею.
  • Если файл изображения исчезает, он автоматически удаляется из галереи.
  • Если файл изображения изменен, изображение необходимо обновить в галерее.
  • Не используйте автоматическое обновление страницы: каждое изображение нужно щелкнуть, чтобы увеличить его в том же полном окне.
  • И, как сказано выше, каждое изображение должно быть доступным для клика, чтобы его можно было увеличить в полный размер от начала координат в одном и том же окне (как здесь для примера: https://www.lightgalleryjs.com/demos/zoom-from-origin). /)

Я сделал это на основе некоторых примеров, найденных в Stackoverflow. Но img не обновляется. И если я хорошо понимаю код, он не удалит изображение, если файл исчезнет. Что вы думаете? (Как видите, я не очень разбираюсь в новых технологиях... Я старый веб-мастер html/css)

<!doctype html>
<html lang = "fr">
<head>
  <meta charset = "utf-8">
  <title>Titre de la page</title>
<link rel = "stylesheet" href = "style.css">

<script>

function refresh(node)
{
   var times = 1000; // gap in Milli Seconds;

   (function startRefresh()
   {
      var address;
      if (node.src.indexOf('?')>-1)
       address = node.src.split('?')[0];
      else 
       address = node.src;
      node.src = address+"?time = "+new Date().getTime();

      setTimeout(startRefresh,times);
   })();

}

window.onload = function()
{
  var node = document.getElementsByClassName('img');
  refresh(node);
  // you can refresh as many images you want just repeat above steps
}

</script>

</head>
<body>

<div class = "ajax-inserted-content">
    <section class = "section gallery grid layout-4-col">
        <div class = "container">
            <div class = "row" id='gallery-items'>
            </div>
        </div>
    </section>
</div>
<script>
function doPortItem(n) {
    let img = document.createElement('img');
    img.src = './imgportfolio/test-' + n + '.jpg';
    img.addEventListener('load', () => {
        let div = `<div class = "col-3 col-lg-4 col-md-6 col-sm-12">
     <div class = "gallery-item">
       <div class = "gallery-img">
         <img class = "img" data-lazy-image data-src = "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzIDIiPjwvc3ZnPg= = " src = "${img.src}" alt = "Demo img"> 
       </div>
     </div>
   </div>`;
        document.querySelector('#gallery-items').innerHTML += div;
        doPortItem(++n)
    })
}
doPortItem(1)
</script>

</body>
</html>

К сожалению, это не то, что вы можете сделать только на стороне клиента. То, что вы описываете, можно сделать с использованием какого-либо процесса на стороне сервера, а затем, возможно, использовать что-то вроде протокола Websocket. Но будьте осторожны: это нетривиальный процесс.

Keith 21.07.2024 15:33

Как сказал @Keith, вам нужно будет сделать это на стороне сервера, посмотрите здесь: stackoverflow.com/a/44588417/4191561

ManuelMB 21.07.2024 17:20

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

Vincent Zorzi 21.07.2024 23:18
Поведение ключевого слова "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) для оценки ваших знаний,...
0
3
51
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Короче говоря: вы не можете читать каталог полностью на основе клиента, потому что это было бы кошмаром безопасности: вы могли бы легко просканировать файловую систему пользователя.

Обходной путь: только на основе клиента: требуется предсказуемая схема именования.

Если вы действительно не можете запустить локальный сервер, поддерживающий серверные сценарии, такие как php, ваш единственный шанс, вероятно, состоит в том, чтобы развернуть согласованную схему числовых имен файлов изображений и скрыть несуществующие изображения в представлении галереи, например от img-1 до img-100:

let dir = 'https://picsum.photos/id';
let suffix = '/100/100';
let start = -3;
let end = 3;

// init
loadImages(dir);

// reload
let interval = 60 * 1000;
setInterval(loadImages, interval);


function loadImages(dir) {
  let html = '';

  //reset content
  imageGrid.innerHTML = '';

  for (let i = start; i < end; i++) {
    let src = `${dir}/${i}${suffix}`;
    html +=
      `<a href = "${dir}/${i}${suffix}" data-lg-size = "100-100">
         <img onerror = "this.parentNode.classList.add('broken-image')" src = "${src}">
      </a>`;
  }
  imageGrid.insertAdjacentHTML('beforeend', html);

}
.imageGrid {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  gap: 1em;
}

img {
  width: 100%;
  aspect-ratio: 1;
  border: 1px solid #ccc;
}

.broken-image {
  display: none;
}
   

<h3>3 images are hidden as they don't exist</h3>
<div id = "imageGrid" class = "imageGrid"></div>
This is rather a hack and by no means great. In fact we're assuming we have 6 images named by a predictable index suffix.

Если изображение не может быть загружено, оно скрыто с помощью функции обратного вызова onerror.

Если вы можете контролировать соглашения об именах файлов — это, вероятно, лучшее, что вы можете получить от 100% клиентского подхода.

Обновление списка файлов

Обновления списка каталогов будут зависеть от повторяющегося вызова метода, например setInterval(). Вы не можете получить правильное обновление в режиме реального времени, и вам, вероятно, следует избегать слишком большого количества обновлений — например, обновление каждую минуту (или каждые 5 минут) более разумно, чем обновление каждую секунду.

Повторная инициализация скриптов галереи

При обновлении галереи вам обычно необходимо инициализировать скрипт галереи (привязка событий лайтбокса и т. д.).

Локальный сервер

Я настоятельно рекомендую установить локальный сервер, обеспечивающий, например, функциональность php. Например, через такое приложение, как xampp, mampp и т. д.

В этом случае вы можете написать скрипт php, отвечающий на вызов JS fetch(), например:

JavaScript
Мы отправляем запрос POST через fetch() на PHP-скрипт, который возвращает список файлов для указанного каталога, включая только определенные типы файлов.

// directory to search for image files
let dir = 'img';

// allowed file extensions
let extensions = ['webp', 'png', 'jpg', 'gif'];

// php script url for directory listing
let phpScan = 'filelist.php';

// update interval: ever minute = 60000ms
let interval = 60 * 1000;

let fileList;

// init async call
(async () => {

    //init
    fileList = await getFilelist(dir, phpScan, extensions);
    updateGallery(fileList);

    setInterval(async () => {
        fileList = await getFilelist(dir, phpScan, extensions);
        updateGallery(fileList)
    }, interval)

})();


// dummy update function
function updateGallery(fileList) {
    console.info(fileList);
}

/**
 * retrieve file directory info 
 * via php script
 */
async function getFilelist(dir, phpScan, extensions) {
    let list = await (await fetch(
        phpScan,
        {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({
                dir: dir,
                extensions: extensions
            })
        })).json();
    return list;
}

Если вы используете локальный сервер, вы также можете использовать этот подход, как описано в fmacdee: «Как составить список файлов внутри папки с помощью выборки?».

Этот подход предполагает, что на вашем локальном сервере включен список каталогов. Другими словами: сервер автоматически сгенерирует представление таблицы HTML, которое вы можете «проанализировать» с помощью получения результата. Вот модифицированная версия:


async function getDirectory(dir, extensions) {
    let response = await fetch(dir);
    let html = await response.text();
    let doc = new DOMParser().parseFromString(html, 'text/html');
    console.info(doc);

    let files = [...doc.querySelectorAll("a")].map(a => {
        // filter allowed extenstion
        let ext = a.href.split('.').slice(-1)[0];
        if (extensions.includes(ext)) {
            let filename = a.href.split('/').slice(-1)[0];
            let mod = a.parentNode.nextElementSibling.textContent.trim()
            return { filename: filename, href: a.href, mod: mod }
        }
        return
    }
    ).filter(Boolean)

    return files;
}

В общем: настоятельно рекомендую потратить время на установку локального сервера.
Мы определенно не увидим никаких новых функций JS, позволяющих просматривать каталоги на стороне клиента, поскольку это будет иметь огромные последствия для безопасности.

Спасибо за такой подробный ответ :D Я попробовал ваш обходной путь только для клиента: он работает. Но поскольку мне нужно получать новые изображения в реальном времени, я вынужден установить интервал в 1 секунду. Итак, я не могу добавить сценарий щелчка и масштабирования к каждому изображению, потому что оно будет обновляться и исчезать каждую секунду. Попробую найти, можно ли установить локальный сервер. Спасибо :)

Vincent Zorzi 24.07.2024 09:38

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