fix backup restore: stream-peek gzip content instead of zlib.gunzipFile (node20 API)
This commit is contained in:
@@ -186,7 +186,8 @@ app.put('/api/settings', requireAdmin, async (req, res) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// --- Backup / Restore ---
|
// --- 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 tar = require('tar');
|
||||||
const os = require('os');
|
const os = require('os');
|
||||||
const uploadBackup = multer({
|
const uploadBackup = multer({
|
||||||
@@ -347,14 +348,38 @@ function cleanupUpload(req) {
|
|||||||
} catch {}
|
} 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) => {
|
app.post('/api/restore', requireAdmin, uploadBackup.single('backup'), async (req, res) => {
|
||||||
if (!req.file) return res.status(400).json({ error: 'backup file required' });
|
if (!req.file) return res.status(400).json({ error: 'backup file required' });
|
||||||
let data;
|
let data;
|
||||||
let legacyPhotos = [];
|
let legacyPhotos = [];
|
||||||
const staging = fs.mkdtempSync(path.join(os.tmpdir(), 'wido-rst-'));
|
const staging = fs.mkdtempSync(path.join(os.tmpdir(), 'wido-rst-'));
|
||||||
try {
|
try {
|
||||||
const gunz = await gunzipFile(req.file.path).catch(() => null);
|
const head = await peekGunzip(req.file.path, 8);
|
||||||
if (gunz && gunz[0] === 0x7b) {
|
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'));
|
data = JSON.parse(gunz.toString('utf8'));
|
||||||
legacyPhotos = data.photos || [];
|
legacyPhotos = data.photos || [];
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Reference in New Issue
Block a user