feat: WebDAV Sync mit vollständiger Ordnerstruktur (user/ordner/unterordner/datei)

This commit is contained in:
2026-06-14 01:46:51 +02:00
parent 5ded22aef7
commit e2d28e285c
2 changed files with 45 additions and 5 deletions

View File

@@ -236,11 +236,28 @@ router.post('/webdav/sync', authenticate, requireAdmin, async (req, res) => {
const cfg = webdav.getConfig(); const cfg = webdav.getConfig();
if (!cfg.enabled) return res.status(400).json({ error: 'WebDAV nicht aktiviert' }); if (!cfg.enabled) return res.status(400).json({ error: 'WebDAV nicht aktiviert' });
// Alle Dateien aus DB holen mit Username // Ordnerpfad rekursiv aus DB auflösen
function getFolderPath(folderId) {
if (!folderId) return '';
const parts = [];
let current = folderId;
const visited = new Set();
while (current) {
if (visited.has(current)) break;
visited.add(current);
const folder = db.prepare('SELECT id, name, parent_id FROM folders WHERE id=?').get(current);
if (!folder) break;
parts.unshift(folder.name.replace(/[/\\]/g, '_'));
current = folder.parent_id;
}
return parts.join('/');
}
// Alle Dateien aus DB holen mit Username und folder_id
const files = db.prepare(` const files = db.prepare(`
SELECT f.*, u.username FROM files f SELECT f.*, u.username FROM files f
JOIN users u ON u.id = f.user_id JOIN users u ON u.id = f.user_id
ORDER BY f.user_id, f.id ORDER BY f.user_id, f.folder_id, f.id
`).all(); `).all();
const results = { ok: 0, failed: 0, errors: [] }; const results = { ok: 0, failed: 0, errors: [] };
@@ -254,7 +271,11 @@ router.post('/webdav/sync', authenticate, requireAdmin, async (req, res) => {
} }
try { try {
const buf = fs.readFileSync(localPath); const buf = fs.readFileSync(localPath);
const davPath = webdav.userPath(cfg, file.username) + '/' + file.originalname; const folderPath = getFolderPath(file.folder_id);
const userBase = webdav.userPath(cfg, file.username);
const davPath = folderPath
? `${userBase}/${folderPath}/${file.originalname}`
: `${userBase}/${file.originalname}`;
await webdav.uploadFile(buf, davPath, file.mimetype || 'application/octet-stream'); await webdav.uploadFile(buf, davPath, file.mimetype || 'application/octet-stream');
results.ok++; results.ok++;
} catch(e) { } catch(e) {

View File

@@ -200,11 +200,30 @@ router.post('/', authenticate, (req, res) => {
.run(uid, req.file.filename, req.file.originalname, req.file.mimetype||'application/octet-stream', req.file.size, folderId); .run(uid, req.file.filename, req.file.originalname, req.file.mimetype||'application/octet-stream', req.file.size, folderId);
const newFile = db.prepare('SELECT f.*,u.username as owner FROM files f JOIN users u ON u.id=f.user_id WHERE f.id=?').get(r.lastInsertRowid); const newFile = db.prepare('SELECT f.*,u.username as owner FROM files f JOIN users u ON u.id=f.user_id WHERE f.id=?').get(r.lastInsertRowid);
// WebDAV: Datei asynchron spiegeln (Fehler ignorieren, lokale Kopie bleibt) // WebDAV: Datei asynchron spiegeln mit Ordnerstruktur
const cfg = webdav.getConfig(); const cfg = webdav.getConfig();
if (cfg.enabled) { if (cfg.enabled) {
const user = db.prepare('SELECT username FROM users WHERE id=?').get(uid); const user = db.prepare('SELECT username FROM users WHERE id=?').get(uid);
const davPath = webdav.userPath(cfg, user.username) + '/' + req.file.originalname; // Ordnerpfad auflösen
function getFolderPath(fid) {
if (!fid) return '';
const parts = [];
let cur = fid;
const seen = new Set();
while (cur) {
if (seen.has(cur)) break; seen.add(cur);
const fo = db.prepare('SELECT name, parent_id FROM folders WHERE id=?').get(cur);
if (!fo) break;
parts.unshift(fo.name.replace(/[/\\]/g, '_'));
cur = fo.parent_id;
}
return parts.join('/');
}
const folderPath = getFolderPath(folderId);
const userBase = webdav.userPath(cfg, user.username);
const davPath = folderPath
? `${userBase}/${folderPath}/${req.file.originalname}`
: `${userBase}/${req.file.originalname}`;
fs.readFile(path.join(UPLOAD_DIR, req.file.filename), (err, buf) => { fs.readFile(path.join(UPLOAD_DIR, req.file.filename), (err, buf) => {
if (!err) webdav.uploadFile(buf, davPath, req.file.mimetype).catch(e => console.error('[webdav upload]', e.message)); if (!err) webdav.uploadFile(buf, davPath, req.file.mimetype).catch(e => console.error('[webdav upload]', e.message));
}); });