fix: 云端保存API配置写入/data并避免文件不存在
This commit is contained in:
1 parent
202130d153
commit
5753d22e50
3 files changed
+66
-10
No files matched your search
@@ -10,6 +10,7 @@
|
||||
@inject ISnackbar Snackbar
|
||||
@inject IDialogService DialogService
|
||||
@inject IWebHostEnvironment Environment
|
||||
@using TelegramPanel.Web.Services
|
||||
|
||||
<PageTitle>系统设置 - Telegram Panel</PageTitle>
|
||||
|
||||
@@ -150,7 +151,7 @@
|
||||
private int logRetentionDays = 30;
|
||||
private bool syncing = false;
|
||||
|
||||
private string LocalConfigPath => System.IO.Path.Combine(Environment.ContentRootPath, "appsettings.local.json");
|
||||
private string LocalConfigPath => LocalConfigFile.ResolvePath(Configuration, Environment);
|
||||
private bool LocalConfigExists => System.IO.File.Exists(LocalConfigPath);
|
||||
|
||||
protected override void OnInitialized()
|
||||
@@ -188,8 +189,18 @@
|
||||
// 配置变更后清理客户端缓存,确保后续操作使用新 ApiId/ApiHash
|
||||
await TelegramClientPool.RemoveAllClientsAsync();
|
||||
|
||||
var fileInfo = new System.IO.FileInfo(localConfigPath);
|
||||
Snackbar.Add($"API 配置已保存:{localConfigPath}({fileInfo.Length} bytes)。已清理 Telegram 客户端缓存,后续操作将使用新配置。", Severity.Success);
|
||||
string sizeHint;
|
||||
try
|
||||
{
|
||||
var fileInfo = new System.IO.FileInfo(localConfigPath);
|
||||
sizeHint = $"({fileInfo.Length} bytes)";
|
||||
}
|
||||
catch
|
||||
{
|
||||
sizeHint = "";
|
||||
}
|
||||
|
||||
Snackbar.Add($"API 配置已保存:{localConfigPath}{sizeHint}。已清理 Telegram 客户端缓存,后续操作将使用新配置。", Severity.Success);
|
||||
StateHasChanged();
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -240,11 +251,9 @@
|
||||
private async Task SaveLocalConfigAsync(System.Text.Json.Nodes.JsonObject root)
|
||||
{
|
||||
var json = root.ToJsonString(new System.Text.Json.JsonSerializerOptions { WriteIndented = true });
|
||||
await System.IO.File.WriteAllTextAsync(
|
||||
LocalConfigPath,
|
||||
json,
|
||||
new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier: false)
|
||||
);
|
||||
var path = LocalConfigPath;
|
||||
await LocalConfigFile.EnsureExistsAsync(path);
|
||||
await LocalConfigFile.WriteJsonAtomicallyAsync(path, json);
|
||||
}
|
||||
|
||||
private static System.Text.Json.Nodes.JsonObject EnsureObject(System.Text.Json.Nodes.JsonObject root, string key)
|
||||
|
||||
@@ -18,7 +18,7 @@ var builder = WebApplication.CreateBuilder(args);
|
||||
// 直接加载会抛 FileNotFoundException 导致容器不断重启,因此这里先确保文件存在一个空 JSON。
|
||||
try
|
||||
{
|
||||
var localOverridePath = Path.Combine(builder.Environment.ContentRootPath, "appsettings.local.json");
|
||||
var localOverridePath = LocalConfigFile.ResolvePath(builder.Configuration, builder.Environment);
|
||||
if (!File.Exists(localOverridePath))
|
||||
File.WriteAllText(localOverridePath, "{}", new System.Text.UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
|
||||
}
|
||||
@@ -31,7 +31,8 @@ try
|
||||
{
|
||||
// 注意:如果该路径是“悬空符号链接”,配置系统可能会认为文件存在并尝试打开,从而抛 FileNotFoundException。
|
||||
// 本地覆盖配置不应该阻塞启动,因此这里兜底吞掉 FileNotFoundException。
|
||||
builder.Configuration.AddJsonFile("appsettings.local.json", optional: true, reloadOnChange: true);
|
||||
var localOverridePath = LocalConfigFile.ResolvePath(builder.Configuration, builder.Environment);
|
||||
builder.Configuration.AddJsonFile(localOverridePath, optional: true, reloadOnChange: true);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
using System.Text;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
|
||||
namespace TelegramPanel.Web.Services;
|
||||
|
||||
public static class LocalConfigFile
|
||||
{
|
||||
public static string ResolvePath(IConfiguration configuration, IWebHostEnvironment environment)
|
||||
{
|
||||
var configured = (configuration["LocalConfig:Path"] ?? "").Trim();
|
||||
if (!string.IsNullOrWhiteSpace(configured))
|
||||
return configured;
|
||||
|
||||
// Docker 部署默认持久化目录为 /data(docker-compose 挂载 ./docker-data:/data)
|
||||
// 即便没有显式配置,也优先写到 /data,避免写入镜像层 /app 导致丢失或权限问题。
|
||||
if (Directory.Exists("/data"))
|
||||
return "/data/appsettings.local.json";
|
||||
|
||||
return Path.Combine(environment.ContentRootPath, "appsettings.local.json");
|
||||
}
|
||||
|
||||
public static async Task EnsureExistsAsync(string path, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrWhiteSpace(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
if (File.Exists(path))
|
||||
return;
|
||||
|
||||
await File.WriteAllTextAsync(path, "{}", new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), cancellationToken);
|
||||
}
|
||||
|
||||
public static async Task WriteJsonAtomicallyAsync(string path, string json, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var dir = Path.GetDirectoryName(path);
|
||||
if (!string.IsNullOrWhiteSpace(dir))
|
||||
Directory.CreateDirectory(dir);
|
||||
|
||||
var tmp = $"{path}.tmp";
|
||||
await File.WriteAllTextAsync(tmp, json, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false), cancellationToken);
|
||||
File.Move(tmp, path, overwrite: true);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user