如何在Asp.Net core 2.0 Webapi中写入wwwroot文件?

3
我需要一个非常简单的API来允许发布某些键。这些键应该写在一个文件中,但是在部署应用程序后,我遇到了麻烦,因为我可以在GET请求上读取文件,但是发布却不起作用。
它给我的消息是:
"detail": "拒绝访问路径 '....\Keys\Keys.json'。"
我正在使用以下代码写入文件:
        var path = "wwwroot/Keys/Keys.json";

        var result = new List <FireBaseKeysModel> ( );

        if (System.IO.File.Exists (path)) {
            var initialJson = System.IO.File.ReadAllText (path);
            var convertedJson =
                JsonConvert.DeserializeObject <List <FireBaseKeysModel>> (initialJson);
            try {
                result.AddRange (convertedJson);
            }
            catch  {
                //
            }

        }

        result.Add(new FireBaseKeysModel() {
            AccountId = accountId,
            AditionalInfo = addicionalInfo,
            DeviceInfo = deviceInfo,
            RegistrationKey = registrationKey,
            ClientId = clientId
        });

        var json = JsonConvert.SerializeObject (result.ToArray ( ));

        System.IO.File.WriteAllText (path, json);

有没有办法在不改变服务器权限的情况下解决这个问题?

不需要。如果应用程序需要写入文件夹,则需要该文件夹的写入权限。 - Chris Pratt
很抱歉,您无法访问应用程序文件夹之外的文件。例如,如果您的部署路径是 c:\inetpub\wwwroot\myapp,那么您只能访问 myapp 文件夹内的文件。 - Afshar Mohebi
2个回答

3

我有一个类似的任务,需要将已登录用户上传的文件存储在服务器上。我选择将它们存储在文件夹结构下 wwwroot/uploads/{ 环境 }/{ 用户名 }/{ 年 }/{ 月 }/{ 日 }/

我不能给你确切的答案,但以下是你可能想尝试的步骤。

  1. Enable static file usage

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        ...
    
        // With the usage of static file extensions, you shouldn't need to
        // set permissions to folders, if you decide to go with wwwroot.
        app.UseStaticFiles();
    
        ...
    }
    
  2. Storage service

    public interface IStorageService
    {
        Task<string> UploadAsync(string path, IFormFile content, string 
            nameWithoutExtension = null);
    }
    
    public class LocalFileStorageService : IStorageService
    {
        private readonly IHostingEnvironment _env;
    
        public LocalFileStorageService(IHostingEnvironment env)
        {
            _env = env;
        }
    
        public async Task<string> UploadAsync(string path, IFormFile content, 
            string nameWithoutExtension = null)
        {
            if (content != null && content.Length > 0)
            {
                string extension = Path.GetExtension(content.FileName);
    
                // Never trust user's provided file name
                string fileName = $"{ nameWithoutExtension ?? Guid.NewGuid().ToString() }{ extension }";
    
                // Combine the path with web root and my folder of choice, 
                // "uploads" 
                path = Path.Combine(_env.WebRootPath, "uploads", path).ToLower();
    
                // If the path doesn't exist, create it.
                // In your case, you might not need it if you're going 
                // to make sure your `keys.json` file is always there.
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
    
                // Combine the path with the file name
                string fullFileLocation = Path.Combine(path, fileName).ToLower();
    
                // If your case, you might just need to open your 
                // `keys.json` and append text on it.
                // Note that there is FileMode.Append too you might want to
                // take a look.
                using (var fileStream = new FileStream(fullFileLocation, FileMode.Create))
                {
                   await Content.CopyToAsync(fileStream);
                }
    
                // I only want to get its relative path
                return fullFileLocation.Replace(_env.WebRootPath, 
                    String.Empty, StringComparison.OrdinalIgnoreCase);
            }
    
            return String.Empty;
        }
    }
    

2

如果不修改该文件夹的权限,就没有修复它的方法。(由于您使用了System.IO,我假设这是Windows和IIS)。工作进程通常使用运行应用程序池的帐户。

默认情况下,此帐户应仅具有对该文件夹的读取访问权限。除非至少授予写入权限,否则无法绕过此问题。

小离题评论:我不会硬编码wwwroot文件夹,因为该文件夹的名称受配置对象的影响,很可能会更改,我将使用内置的IHostingEnvironment和依赖项注入来获取路径:

private IHostingEnvironment _env;
public FooController(IHostingEnvironment env) {
    _env = env;
}

var webrootFolder = _env.WebRootPath

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接