feat(update): auto-clean old desktop installer packages
This commit is contained in:
@@ -104,6 +104,8 @@ const DOWNLOAD_SIGNED_URL_EXPIRES_SECONDS = Math.max(
|
|||||||
const DEFAULT_DESKTOP_VERSION = process.env.DESKTOP_LATEST_VERSION || '0.1.2';
|
const DEFAULT_DESKTOP_VERSION = process.env.DESKTOP_LATEST_VERSION || '0.1.2';
|
||||||
const DEFAULT_DESKTOP_INSTALLER_URL = process.env.DESKTOP_INSTALLER_URL || '';
|
const DEFAULT_DESKTOP_INSTALLER_URL = process.env.DESKTOP_INSTALLER_URL || '';
|
||||||
const DEFAULT_DESKTOP_RELEASE_NOTES = process.env.DESKTOP_RELEASE_NOTES || '';
|
const DEFAULT_DESKTOP_RELEASE_NOTES = process.env.DESKTOP_RELEASE_NOTES || '';
|
||||||
|
const DESKTOP_INSTALLERS_DIR = path.resolve(__dirname, '../frontend/downloads');
|
||||||
|
const DESKTOP_INSTALLER_FILE_PATTERN = /^wanwan-cloud-desktop_.*_x64-setup\.exe$/i;
|
||||||
const RESUMABLE_UPLOAD_SESSION_TTL_MS = Number(process.env.RESUMABLE_UPLOAD_SESSION_TTL_MS || (24 * 60 * 60 * 1000)); // 24小时
|
const RESUMABLE_UPLOAD_SESSION_TTL_MS = Number(process.env.RESUMABLE_UPLOAD_SESSION_TTL_MS || (24 * 60 * 60 * 1000)); // 24小时
|
||||||
const RESUMABLE_UPLOAD_CHUNK_SIZE_BYTES = Number(process.env.RESUMABLE_UPLOAD_CHUNK_SIZE_BYTES || (4 * 1024 * 1024)); // 4MB
|
const RESUMABLE_UPLOAD_CHUNK_SIZE_BYTES = Number(process.env.RESUMABLE_UPLOAD_CHUNK_SIZE_BYTES || (4 * 1024 * 1024)); // 4MB
|
||||||
const RESUMABLE_UPLOAD_MAX_CHUNK_SIZE_BYTES = Number(process.env.RESUMABLE_UPLOAD_MAX_CHUNK_SIZE_BYTES || (32 * 1024 * 1024)); // 32MB
|
const RESUMABLE_UPLOAD_MAX_CHUNK_SIZE_BYTES = Number(process.env.RESUMABLE_UPLOAD_MAX_CHUNK_SIZE_BYTES || (32 * 1024 * 1024)); // 32MB
|
||||||
@@ -184,6 +186,67 @@ function getDesktopUpdateConfig() {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function resolveDesktopInstallerFileName(installerUrl) {
|
||||||
|
const raw = String(installerUrl || '').trim();
|
||||||
|
if (!raw) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const parsed = new URL(raw, 'http://local.invalid');
|
||||||
|
const pathname = decodeURIComponent(parsed.pathname || '');
|
||||||
|
const fileName = path.basename(pathname);
|
||||||
|
return fileName && fileName !== '.' && fileName !== '/' ? fileName : null;
|
||||||
|
} catch (error) {
|
||||||
|
const sanitized = raw.split('?')[0].split('#')[0];
|
||||||
|
const fileName = path.basename(sanitized);
|
||||||
|
return fileName && fileName !== '.' && fileName !== '/' ? fileName : null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function cleanupDesktopInstallerPackages(installerUrl) {
|
||||||
|
try {
|
||||||
|
const keepFileName = resolveDesktopInstallerFileName(installerUrl);
|
||||||
|
if (!keepFileName || !DESKTOP_INSTALLER_FILE_PATTERN.test(keepFileName)) {
|
||||||
|
return { executed: false, removed: 0, kept: 0, reason: 'installer_url_not_local_package' };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs.existsSync(DESKTOP_INSTALLERS_DIR)) {
|
||||||
|
return { executed: false, removed: 0, kept: 0, reason: 'downloads_dir_missing' };
|
||||||
|
}
|
||||||
|
|
||||||
|
const candidates = fs.readdirSync(DESKTOP_INSTALLERS_DIR)
|
||||||
|
.filter((name) => DESKTOP_INSTALLER_FILE_PATTERN.test(name));
|
||||||
|
const keepFilePath = path.join(DESKTOP_INSTALLERS_DIR, keepFileName);
|
||||||
|
|
||||||
|
if (!fs.existsSync(keepFilePath)) {
|
||||||
|
return { executed: false, removed: 0, kept: candidates.length, reason: 'keep_package_missing' };
|
||||||
|
}
|
||||||
|
|
||||||
|
let removed = 0;
|
||||||
|
for (const fileName of candidates) {
|
||||||
|
if (fileName === keepFileName) continue;
|
||||||
|
fs.unlinkSync(path.join(DESKTOP_INSTALLERS_DIR, fileName));
|
||||||
|
removed += 1;
|
||||||
|
console.log(`[桌面端更新] 已清理旧安装包: ${fileName}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
executed: true,
|
||||||
|
removed,
|
||||||
|
kept: candidates.length - removed,
|
||||||
|
keep_file: keepFileName
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[桌面端更新] 清理旧安装包失败:', error);
|
||||||
|
return {
|
||||||
|
executed: false,
|
||||||
|
removed: 0,
|
||||||
|
kept: 0,
|
||||||
|
reason: 'cleanup_failed',
|
||||||
|
error: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function getResolvedStorageRoot() {
|
function getResolvedStorageRoot() {
|
||||||
const configuredRoot = process.env.STORAGE_ROOT;
|
const configuredRoot = process.env.STORAGE_ROOT;
|
||||||
if (!configuredRoot) {
|
if (!configuredRoot) {
|
||||||
@@ -8693,6 +8756,7 @@ app.post('/api/admin/settings',
|
|||||||
download_security,
|
download_security,
|
||||||
desktop_update
|
desktop_update
|
||||||
} = req.body;
|
} = req.body;
|
||||||
|
let desktopInstallerCleanup = null;
|
||||||
|
|
||||||
if (max_upload_size !== undefined) {
|
if (max_upload_size !== undefined) {
|
||||||
const size = parseInt(max_upload_size);
|
const size = parseInt(max_upload_size);
|
||||||
@@ -8759,8 +8823,10 @@ app.post('/api/admin/settings',
|
|||||||
SettingsDB.set('desktop_latest_version', normalizeVersion(desktop_update.latest_version, DEFAULT_DESKTOP_VERSION));
|
SettingsDB.set('desktop_latest_version', normalizeVersion(desktop_update.latest_version, DEFAULT_DESKTOP_VERSION));
|
||||||
}
|
}
|
||||||
if (desktop_update.installer_url !== undefined) {
|
if (desktop_update.installer_url !== undefined) {
|
||||||
SettingsDB.set('desktop_installer_url', String(desktop_update.installer_url || '').trim());
|
const normalizedInstallerUrl = String(desktop_update.installer_url || '').trim();
|
||||||
SettingsDB.set('desktop_installer_url_win_x64', String(desktop_update.installer_url || '').trim());
|
SettingsDB.set('desktop_installer_url', normalizedInstallerUrl);
|
||||||
|
SettingsDB.set('desktop_installer_url_win_x64', normalizedInstallerUrl);
|
||||||
|
desktopInstallerCleanup = cleanupDesktopInstallerPackages(normalizedInstallerUrl);
|
||||||
}
|
}
|
||||||
if (desktop_update.release_notes !== undefined) {
|
if (desktop_update.release_notes !== undefined) {
|
||||||
SettingsDB.set('desktop_release_notes', String(desktop_update.release_notes || '').trim());
|
SettingsDB.set('desktop_release_notes', String(desktop_update.release_notes || '').trim());
|
||||||
@@ -8770,10 +8836,14 @@ app.post('/api/admin/settings',
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
res.json({
|
const payload = {
|
||||||
success: true,
|
success: true,
|
||||||
message: '系统设置已更新'
|
message: '系统设置已更新'
|
||||||
});
|
};
|
||||||
|
if (desktopInstallerCleanup) {
|
||||||
|
payload.desktop_installer_cleanup = desktopInstallerCleanup;
|
||||||
|
}
|
||||||
|
res.json(payload);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('更新系统设置失败:', error);
|
console.error('更新系统设置失败:', error);
|
||||||
res.status(500).json({
|
res.status(500).json({
|
||||||
@@ -10788,6 +10858,10 @@ app.get("/s/:code", (req, res) => {
|
|||||||
|
|
||||||
// 启动时清理旧临时文件
|
// 启动时清理旧临时文件
|
||||||
cleanupOldTempFiles();
|
cleanupOldTempFiles();
|
||||||
|
const desktopCleanupOnStartup = cleanupDesktopInstallerPackages(getDesktopUpdateConfig().installerUrl);
|
||||||
|
if (desktopCleanupOnStartup.executed && desktopCleanupOnStartup.removed > 0) {
|
||||||
|
console.log(`[桌面端更新] 启动时已清理 ${desktopCleanupOnStartup.removed} 个旧安装包`);
|
||||||
|
}
|
||||||
|
|
||||||
// 启动服务器
|
// 启动服务器
|
||||||
app.listen(PORT, '0.0.0.0', () => {
|
app.listen(PORT, '0.0.0.0', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user