Node.js
Как получить содержимое директории и поддиректорий в Node.js Express
Короткий ответ: используйте fs.promises.readdir() для чтения папки и рекурсивную функцию для обхода поддиректорий. В Express результат можно вернуть как JSON, но путь к папке нужно ограничить, чтобы пользователь не мог прочитать произвольные файлы сервера
Запрос «node js express js как получить содержимое директории и всех поддиректорий в искомой» выглядит узко, но задача встречается часто: показать список файлов, построить файловый индекс, найти документы, вывести медиатеку или просканировать папку проекта
Пример структуры
project/
server.js
storage/
readme.txt
docs/
guide.txt
images/
logo.png
Нужно получить список файлов внутри storage, включая вложенные папки
Рекурсивная функция обхода
Файл server.js
const express = require("express");
const fs = require("fs/promises");
const path = require("path");
const app = express();
const storageRoot = path.join(__dirname, "storage");
async function walkDirectory(directoryPath) {
const entries = await fs.readdir(directoryPath, {
withFileTypes: true
});
const result = [];
for (const entry of entries) {
const fullPath = path.join(directoryPath, entry.name);
const relativePath = path.relative(storageRoot, fullPath);
if (entry.isDirectory()) {
const children = await walkDirectory(fullPath);
result.push({
type: "directory",
name: entry.name,
path: relativePath,
children
});
} else {
result.push({
type: "file",
name: entry.name,
path: relativePath
});
}
}
return result;
}
app.get("/files", async (request, response, next) => {
try {
const files = await walkDirectory(storageRoot);
response.json(files);
} catch (error) {
next(error);
}
});
app.listen(3000, () => {
console.log("Сервер запущен: http://localhost:3000");
});
Откройте
http://localhost:3000/files
Вы получите JSON со списком папок и файлов
Почему withFileTypes полезен
Если вызвать fs.readdir() без withFileTypes, вы получите только имена. Потом придется отдельно делать stat для каждого файла, чтобы понять, файл это или папка
С withFileTypes: true Node.js возвращает объекты Dirent, у которых есть методы isDirectory() и isFile()
Как вернуть плоский список
Иногда удобнее не дерево, а плоский список путей
async function walkFlat(directoryPath) {
const entries = await fs.readdir(directoryPath, { withFileTypes: true });
const result = [];
for (const entry of entries) {
const fullPath = path.join(directoryPath, entry.name);
if (entry.isDirectory()) {
result.push(...await walkFlat(fullPath));
} else {
result.push(path.relative(storageRoot, fullPath));
}
}
return result;
}
Такой формат удобен для поиска и фильтрации
Безопасность пути
Не давайте пользователю напрямую передавать путь вроде ../../. Если нужно выбирать папку из запроса, проверяйте, что итоговый путь остается внутри разрешенной директории
function resolveStoragePath(userPath) {
const fullPath = path.resolve(storageRoot, userPath);
if (!fullPath.startsWith(storageRoot)) {
throw new Error("Недопустимый путь");
}
return fullPath;
}
Это защищает сервер от чтения чужих системных файлов
Как фильтровать по расширению
Например, только .txt
if (entry.isFile() && entry.name.endsWith(".txt")) {
result.push({
type: "file",
name: entry.name,
path: relativePath
});
}
Для более серьезной фильтрации лучше учитывать регистр, MIME-типы и требования проекта
Мини-практика
Создайте папку storage, добавьте несколько файлов и подпапок, запустите сервер и откройте /files. Затем сделайте второй маршрут /files-flat, который возвращает плоский список путей
Дополнительное упражнение: добавьте фильтр ?ext=.txt, чтобы показывать только файлы с нужным расширением
Частые ошибки
Путь работает только из одной папки запуска Используйте __dirname и path.join, а не относительный путь наугад
Рекурсия падает на ошибке доступа Некоторые папки могут быть недоступны. Обрабатывайте ошибки и не сканируйте системные директории без необходимости
Пользователь может прочитать чужие файлы Проверяйте путь и ограничивайте чтение одной разрешенной папкой
Слишком большая директория тормозит сервер Для огромных деревьев файлов нужна пагинация, кеширование или отдельная фоновая индексация
Что почитать дальше по Node.js
Если нужен общий маршрут по теме, откройте рубрику Node.js. Для соседних задач пригодятся эти разборы:
- Как в Node.js Express отдать файл по ссылке: sendFile и static
- Как достать данные из модуля с базой в Node.js Express
- Как запустить сервер Node.js: простой HTTP-сервер и Express
- Как правильно настроить маршрут в Node.js, Express и Mongoose