[ 'auth_mode' => 'plain', 'access_key_id' => 'plain', 'access_key_secret' => 'secret', 'bucket' => 'plain', 'endpoint' => 'plain', 'prefix' => 'plain', 'ram_role_name' => 'plain', 'custom_domain' => 'plain', 'internal_endpoint' => 'plain', 'https' => 'plain', ], 'cos' => [ 'auth_mode' => 'plain', 'secret_id' => 'plain', 'secret_key' => 'secret', 'bucket' => 'plain', 'region' => 'plain', 'prefix' => 'plain', 'cam_role_name' => 'plain', 'custom_domain' => 'plain', 'https' => 'plain', ], 'qiniu' => [ 'access_key' => 'plain', 'secret_key' => 'secret', 'bucket' => 'plain', 'region' => 'plain', 'prefix' => 'plain', 'custom_domain' => 'plain', 'https' => 'plain', ], ]; foreach ($fieldMap as $d => $fields) { $old = storageConfigFor($d); $in = isset($_POST[$d]) && is_array($_POST[$d]) ? $_POST[$d] : []; $clearSecrets = !empty($in['clear_secrets']); $new = []; foreach ($fields as $f => $kind) { $posted = isset($in[$f]) ? trim((string)$in[$f]) : ''; if ($kind === 'secret') { if ($clearSecrets) { $new[$f] = ''; } else { // 留空表示保持原值 $new[$f] = $posted === '' ? (string)($old[$f] ?? '') : $posted; } } else { $new[$f] = $posted !== '' ? $posted : (string)($old[$f] ?? ''); } } // 复选框型字段(未勾选时浏览器不提交该字段,必须显式归零而不是沿用旧值) $new['https'] = ($new['https'] ?? '') === '0' ? '0' : '1'; if ($d === 'oss') { $new['internal_endpoint'] = ($new['internal_endpoint'] ?? '') === '1' ? '1' : '0'; } saveStorageConfig($d, $new); } setSetting('storage_driver', $driver); // 图片访问方式:direct(直连存储)/ proxy(经 media.php 服务端代理读取) $accessMode = ($_POST['storage_access_mode'] ?? 'direct') === 'proxy' ? 'proxy' : 'direct'; setSetting('storage_access_mode', $accessMode); $message = '设置已保存。当前存储方式:' . (storageDriverLabels()[$driver] ?? $driver) . ';图片访问方式:' . ($accessMode === 'proxy' ? '服务端代理' : '直连存储'); } // ---------- 清除错误提示 ---------- if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'clear_storage_error') { storageClearError(); $message = '已清除错误提示'; } // ---------- 切换界面主题(个人偏好,只影响当前账号)---------- if ($_SERVER['REQUEST_METHOD'] === 'POST' && ($_POST['action'] ?? '') === 'save_theme') { $themeKey = (string)($_POST['theme'] ?? ''); if (!isValidTheme($themeKey)) { $error = '没有这套主题,请从下面重新选一个。'; } elseif (setAdminTheme((int)$admin['id'], $themeKey)) { // setAdminTheme 已经把 session 一起更新了,所以本次请求往下渲染时就已经是新主题 $message = '界面主题已切换为「' . themeInfo($themeKey)['name'] . '」。'; } else { $error = '主题保存失败,请稍后再试。'; } } $themes = themeCatalog(); $curThemeKey = currentThemeKey(); $drivers = storageDriverLabels(); $current = currentStorageDriver(); $configs = []; foreach (['oss', 'cos', 'qiniu'] as $d) { $configs[$d] = storageConfigFor($d); } $lastError = storageLastError(); $isRemote = storageIsRemote(); $remoteReady = $current !== 'local' && storageConfigComplete($current); // 本地图片统计(只读目录,不查库) function localImageStat() { $count = 0; $bytes = 0; $base = UPLOAD_DIR; if (!is_dir($base)) return ['count' => 0, 'bytes' => 0]; $it = new RecursiveIteratorIterator( new RecursiveDirectoryIterator($base, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::LEAVES_ONLY ); foreach ($it as $f) { if (!$f->isFile()) continue; if ($f->getFilename() === '.htaccess') continue; $count++; $bytes += $f->getSize(); } return ['count' => $count, 'bytes' => $bytes]; } $localStat = localImageStat(); ?> >
uploads/ 目录下的图片逐个上传到当前对象存储,并按内容指纹重命名
(<md5前12位>_<随机6位>.扩展名),同时自动改写数据库里对应的图片引用,
因此已有记录不会裂图。已经是本内容指纹名的文件会跳过改名,重复迁移是安全的。