photo_server_json_flutter_c.../api_v1/scanner/scanCartella.js
2026-03-06 10:40:46 +01:00

99 lines
No EOL
3.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// scanner/scanCartella.js
const path = require('path');
const fsp = require('fs/promises');
const processFile = require('./processFile');
const { sha256 } = require('./utils');
const { SUPPORTED_EXTS } = require('../config');
/**
* Scansiona ricorsivamente una cartella e ritorna SOLO i cambiamenti
* (nuovi/modificati) rispetto a previousIndex (mappa { id: meta }).
*
* @param {string} userName - Nome utente (es. "Fabio" o "Common")
* @param {string} cartella - Nome della cartella logica sotto "original" (es. "2017Irlanda19-29ago")
* @param {string} absCartella - Percorso assoluto della cartella da scansionare (p.es. .../photos/<Utente>/original/<cartella>)
* @param {Object} previousIndex- Mappa dell'indice precedente: { <id>: meta }
* @returns {Promise<Array<Object>>} changes - Lista dei soli meta cambiati o nuovi
*/
async function scanCartella(userName, cartella, absCartella, previousIndex) {
const changes = [];
async function walk(currentAbs, relPath = '') {
let entries = [];
try {
entries = await fsp.readdir(currentAbs, { withFileTypes: true });
} catch (err) {
// Cartella non leggibile: logga e prosegui (non bloccare la scansione globale)
console.error(`[SCAN] Impossibile leggere: ${currentAbs} - ${err.message}`);
return;
}
for (const e of entries) {
const absPath = path.join(currentAbs, e.name);
if (e.isDirectory()) {
await walk(absPath, path.join(relPath, e.name));
continue;
}
// Filtra estensioni non supportate
const ext = path.extname(e.name).toLowerCase();
if (!SUPPORTED_EXTS.has(ext)) continue;
// Percorso relativo POSIX (usato per mantenere slash '/')
const fileRelPath = relPath ? `${relPath}/${e.name}` : e.name;
// ID deterministico: user/cartella/relPath
const id = sha256(`${userName}/${cartella}/${fileRelPath}`);
// Confronto con indice precedente per saltare "unchanged"
let st;
try {
st = await fsp.stat(absPath);
} catch (err) {
// File sparito o non accessibile: salta
console.warn(`[SCAN] stat fallita: ${absPath} - ${err.message}`);
continue;
}
const prev = previousIndex[id];
const unchanged =
prev &&
prev.size_bytes === st.size &&
prev.mtimeMs === st.mtimeMs;
if (unchanged) continue; // nulla da aggiornare
// Estrae metadati (EXIF, mime, dimensioni, thumbs, ecc.)
const meta = await processFile(
userName,
cartella,
fileRelPath,
absPath,
ext,
st
);
// ID sempre presente
meta.id = id;
// 🔧 Canonicalizza SEMPRE il path pubblicato nellindex:
// /photos/<Utente>/original/<cartella>/<fileRelPath>
{
// Normalizza separatori e rimuove eventuali leading-slash multipli
const relPosix = String(fileRelPath).replace(/\\/g, '/').replace(/^\/+/, '');
// Costruisci il path canonico e comprimi eventuali '//' in '/'
const canonical = `/photos/${userName}/original/${cartella}/${relPosix}`.replace(/\/+/g, '/');
meta.path = canonical;
// NB: thub1/thub2 rimangono quelli prodotti da processFile (ok per immagini e video)
}
changes.push(meta);
}
}
await walk(absCartella);
return changes;
}
module.exports = scanCartella;