fix(upload): 上传与用户设置目录改为持久化目录并保留旧目录回退

- 上传目录默认 process.cwd()/public/uploads,支持 UPLOAD_DIR 覆盖,避免代码部署覆盖用户上传文件

- 用户设置目录默认 process.cwd()/data,支持 DATA_DIR 覆盖,旧 data/user_settings.json 自动回退读取
这个提交包含在:
xcbyy
2026-10-26 10:49:10 +08:00
父节点 5fcfd54961
当前提交 eb81ef8133

查看文件

@@ -161,12 +161,20 @@ app.use(
})
);
// 静态文件与对象存储目录配置
const uploadDir = path.resolve(__dirname, '../public/uploads');
// 静态文件与对象存储目录配置(优先持久化目录 process.cwd()/public/uploads,避免代码构建部署覆盖用户上传文件)
const persistentUploadDir = process.env.UPLOAD_DIR
? path.resolve(process.env.UPLOAD_DIR)
: path.resolve(process.cwd(), 'public/uploads');
const fallbackUploadDir = path.resolve(__dirname, '../public/uploads');
const uploadDir = persistentUploadDir;
if (!fs.existsSync(uploadDir)) {
fs.mkdirSync(uploadDir, { recursive: true });
}
app.use('/uploads', express.static(uploadDir));
if (uploadDir !== fallbackUploadDir && fs.existsSync(fallbackUploadDir)) {
app.use('/uploads', express.static(fallbackUploadDir));
}
// Multer 文件上传引擎配置
const storage = multer.diskStorage({
@@ -4226,7 +4234,9 @@ app.post('/api/users/:id/profile', async (req: Request, res: Response) => {
// 7.2.1.b 用户隐私安全与通知订阅偏好持久化接口
// 用户设置文件存放于对外不可见的私有目录,避免被 /uploads 静态服务公开读取
const userSettingsDir = path.resolve(__dirname, '../data');
const userSettingsDir = process.env.DATA_DIR
? path.resolve(process.env.DATA_DIR)
: path.resolve(process.cwd(), 'data');
if (!fs.existsSync(userSettingsDir)) {
try {
fs.mkdirSync(userSettingsDir, { recursive: true });
@@ -4235,12 +4245,17 @@ if (!fs.existsSync(userSettingsDir)) {
}
}
const userSettingsFilePath = path.resolve(userSettingsDir, 'user_settings.json');
const fallbackUserSettingsFilePath = path.resolve(__dirname, '../data/user_settings.json');
function readAllUserSettings(): Record<string, { privacyHidePhone: boolean; noticeSubscribe: boolean; updatedAt: string }> {
try {
if (fs.existsSync(userSettingsFilePath)) {
const raw = fs.readFileSync(userSettingsFilePath, 'utf-8');
return JSON.parse(raw) || {};
}
if (userSettingsFilePath !== fallbackUserSettingsFilePath && fs.existsSync(fallbackUserSettingsFilePath)) {
const raw = fs.readFileSync(fallbackUserSettingsFilePath, 'utf-8');
return JSON.parse(raw) || {};
}
} catch (e) {
logServerError('userSettings.read', e);
}