fix backup restore: stream-peek gzip content instead of zlib.gunzipFile (node20 API)

This commit is contained in:
dev
2026-09-08 11:38:38 +03:00
parent 8a50b46b7b
commit ea14fd654f
+28 -3
View File
@@ -186,7 +186,8 @@ app.put('/api/settings', requireAdmin, async (req, res) => {
});
// --- Backup / Restore ---
const gunzipFile = require('util').promisify(require('zlib').gunzipFile);
const gunzipAsync = require('util').promisify(require('zlib').gunzip);
const zlib = require('zlib');
const tar = require('tar');
const os = require('os');
const uploadBackup = multer({
@@ -347,14 +348,38 @@ function cleanupUpload(req) {
} catch {}
}
function peekGunzip(filePath, n) {
return new Promise((resolve) => {
const gunz = zlib.createGunzip();
const bufs = [];
let total = 0;
let done = false;
gunz.on('data', (c) => {
if (done) return;
const need = n - total;
bufs.push(c.length > need ? c.subarray(0, need) : c);
total += Math.min(c.length, need);
if (total >= n) {
done = true;
gunz.destroy();
}
});
gunz.on('error', () => resolve(null));
gunz.on('close', () => resolve(Buffer.concat(bufs)));
fs.createReadStream(filePath).pipe(gunz);
});
}
app.post('/api/restore', requireAdmin, uploadBackup.single('backup'), async (req, res) => {
if (!req.file) return res.status(400).json({ error: 'backup file required' });
let data;
let legacyPhotos = [];
const staging = fs.mkdtempSync(path.join(os.tmpdir(), 'wido-rst-'));
try {
const gunz = await gunzipFile(req.file.path).catch(() => null);
if (gunz && gunz[0] === 0x7b) {
const head = await peekGunzip(req.file.path, 8);
if (head && head[0] === 0x7b) {
const buf = await fs.promises.readFile(req.file.path);
const gunz = await gunzipAsync(buf);
data = JSON.parse(gunz.toString('utf8'));
legacyPhotos = data.photos || [];
} else {