You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在Asp.Net Core 2.0 WebApi中写入wwwroot文件(无需改服务器权限)

解决ASP.NET中POST请求写入文件权限被拒的问题(无需修改服务器权限)

嘿,这个权限坑我之前踩过!不用改服务器权限的话,有几个实用的方案可以解决:

1. 切换到应用专属的私有存储路径

wwwroot是静态文件目录,默认权限配置通常更偏向只读,尤其是生产环境。你可以改用应用根目录下的专用文件夹来存需要写入的文件,比如新建一个Data文件夹——应用进程对自己的目录肯定有读写权限。

代码示例:

首先在控制器里注入IWebHostEnvironment(ASP.NET Core的标配服务):

private readonly IWebHostEnvironment _webHostEnv;

public YourApiController(IWebHostEnvironment webHostEnv)
{
    _webHostEnv = webHostEnv;
}

然后在POST方法里构建安全的文件路径:

// 构建应用根目录下Data文件夹的绝对路径
var storagePath = Path.Combine(_webHostEnv.ContentRootPath, "Data");
// 确保文件夹存在,避免写入时报错
Directory.CreateDirectory(storagePath);
var filePath = Path.Combine(storagePath, "Keys.json");

// 剩下的读写逻辑和你原来的一致
var result = new List<FireBaseKeysModel>();
if (File.Exists(filePath))
{
    var initialJson = File.ReadAllText(filePath);
    var convertedJson = JsonConvert.DeserializeObject<List<FireBaseKeysModel>>(initialJson);
    if (convertedJson != null)
    {
        result.AddRange(convertedJson);
    }
}
result.Add(new FireBaseKeysModel 
{ 
    AccountId = accountId, 
    AditionalInfo = addicionalInfo, 
    DeviceInfo = deviceInfo, 
    RegistrationKey = registrationKey, 
    ClientId = clientId 
});
var json = JsonConvert.SerializeObject(result.ToArray());
File.WriteAllText(filePath, json);

2. 明确指定wwwroot的绝对路径(如果非要用wwwroot)

如果你坚持要存在wwwroot里,别用相对路径——POST请求的当前工作目录可能和GET不一样,导致权限上下文出错。用IWebHostEnvironment.WebRootPath获取wwwroot的绝对路径:

var wwwrootPath = _webHostEnv.WebRootPath;
var keysFolderPath = Path.Combine(wwwrootPath, "Keys");
Directory.CreateDirectory(keysFolderPath); // 确保文件夹存在
var filePath = Path.Combine(keysFolderPath, "Keys.json");

这个方法不一定100%生效,但比相对路径靠谱很多,因为它明确指向了正确的目录。

3. 内存缓存+定时持久化(适合写入不频繁的场景)

如果你的密钥写入操作不是特别频繁,可以先把数据存在内存缓存里,再用后台任务定期写入文件。这样既避免了实时写入的权限冲突,还能提升接口响应速度。

代码示例:

先注入IMemoryCache

private readonly IMemoryCache _memoryCache;
private readonly IWebHostEnvironment _webHostEnv;
private const string KeysCacheKey = "FirebaseKeysCache";

public YourApiController(IMemoryCache memoryCache, IWebHostEnvironment webHostEnv)
{
    _memoryCache = memoryCache;
    _webHostEnv = webHostEnv;
}

然后在POST方法里操作缓存:

// 先从缓存读取数据,没有的话从文件加载
if (!_memoryCache.TryGetValue(KeysCacheKey, out List<FireBaseKeysModel> keysList))
{
    var filePath = Path.Combine(_webHostEnv.ContentRootPath, "Data", "Keys.json");
    keysList = new List<FireBaseKeysModel>();
    if (File.Exists(filePath))
    {
        var initialJson = File.ReadAllText(filePath);
        keysList = JsonConvert.DeserializeObject<List<FireBaseKeysModel>>(initialJson) ?? new List<FireBaseKeysModel>();
    }
    // 缓存1小时,滑动过期
    _memoryCache.Set(KeysCacheKey, keysList, new MemoryCacheEntryOptions 
    { 
        SlidingExpiration = TimeSpan.FromHours(1) 
    });
}

// 添加新密钥到缓存
keysList.Add(new FireBaseKeysModel 
{ 
    AccountId = accountId, 
    AditionalInfo = addicionalInfo, 
    DeviceInfo = deviceInfo, 
    RegistrationKey = registrationKey, 
    ClientId = clientId 
});
_memoryCache.Set(KeysCacheKey, keysList);

// 启动后台任务写入文件(生产环境建议用IHostedService或Hangfire替代Task.Run)
Task.Run(() => 
{
    var filePath = Path.Combine(_webHostEnv.ContentRootPath, "Data", "Keys.json");
    var json = JsonConvert.SerializeObject(keysList.ToArray());
    File.WriteAllText(filePath, json);
});

额外注意点:

不管用哪个方案,都要先检查并创建目标文件夹,不然File.WriteAllText会因为文件夹不存在报错,记得加Directory.CreateDirectory(Path.GetDirectoryName(filePath));

内容的提问来源于stack exchange,提问作者THingamagick

火山引擎 最新活动