How can I write to a file in wwwroot with Asp.Net core 2.0 Webapi

10,293

Solution 1

I have similar task that I need to take logged-in users' upload files and store them on the server. I chose to store them under the folder structure wwwroot/uploads/{ environment }/{ username }/{ YYYY }/{ MM }/{ DD }/.

I am not giving you the exact answer to your problem but these are the steps you might want to try.

  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;
        }
    }
    

Solution 2

There should not be a way to fix it without modifying permissions on that folder. (Since you are using System.IO I'm assuming this is Windows and IIS). The worker process usually uses the account that is running the application pool.

By default this account should only have read access to that folder. Without giving him, at least write permission, there should be no way to work around it.

Small off-topic comment: I would not hardcode the wwwroot folder, since the name of that folder is object to configuration and could very well change, I'd use the built in IHostingEnvironment and dependency injection to get the path:

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

var webrootFolder = _env.WebRootPath
Share:
10,293
THingamagick
Author by

THingamagick

Updated on July 22, 2022

Comments

  • THingamagick
    THingamagick almost 2 years

    I need a very simple API to allow for the Posting of certain keys. This keys should be written on a file, but I am having trouble after deploying the app, as I can read the file on a GET Request but the posting does not work.

    The message it gives me is

    "detail": "Access to the path '....\Keys\Keys.json' is denied.",

    Code I am using to write to file:

            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);
    

    Anyway I can fix this without needint to change permissions on the server itself?

    • Chris Pratt
      Chris Pratt over 6 years
      No. If the app needs to write to a folder then it needs write permissions on that folder.
    • Afshar Mohebi
      Afshar Mohebi over 6 years
      I am afraid you are not allowed to access filed outside of your application's folder. For example if your deploy path is c:\inetpub\wwwroot\myapp, then you can only access files inside myapp folder only.