Search code examples
imageapiasp.net-coreregistration

How to create subfolder based on user name in .NET Core on image upload?


I am trying to create a sub folder inside an already created folder every time an user registers so that every video/image a user whats to upload to go in the folder of that specific user.My problem is that i can't get it to work for some reason.I have an auto generated controller that adds the user and a method that uploads an image to the server.

  [HttpPost]
    public async Task<ActionResult<User>> PostUser(User user)
    {
      
        _context.User.Add(user);
        if (string.IsNullOrWhiteSpace(_env.WebRootPath))
        {
            _env.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
        }
     
        if(user!=null)
        { 
        var users = Path.Combine(_env.WebRootPath,"uploads",user.Name);
        Directory.CreateDirectory(users);
        }
        await _context.SaveChangesAsync();

        return CreatedAtAction("GetUser", new { id = user.IdUser }, user);
    }

Here i try to create a sub folder inside "uploads" folder as the other is already created when the user uploads an image for the first time.The problem is that no matter what I do,it doesn't get created.On top of that I would like to save the image directly to the user folder.For now i can save it only in "uploads" folder.This is my method for the image upload:

  [HttpPost]
    public async Task PostImage(IFormFile file)
    {
       
        if (string.IsNullOrWhiteSpace(_env.WebRootPath))
        {
            _env.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
        }
     
        var uploads = Path.Combine(_env.WebRootPath, "uploads");
        if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);
        if (file.Length > 0)
        {
            using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }   
        }
    }

I have also tried to declare a User property inside the PostImage() method but the user is null in the moment I post the image as the registration is made at the same time with the image upload so automatically it will not work.I also tried to play around with the client side and check if the user has been saved and then to proceed with uploading the file,but without any luck.Can someone please point me into the right direction?


Solution

  • Obviously, when PostImage stores images, your path only reaches uploads folder, not subfolders, so the images will only be stored under the uploads folder.

    If you want to store the images in the corresponding uploads/username folder, you also need to obtain the user information corresponding to the current uploaded image.

    As you said, this is a registration page, so the user's information and images can be passed to the action at the same time. You don't need to use the two post methods, just merge them.

    View:

    @model User
    @{
        ViewData["Title"] = "Index";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    <h1>Index</h1>
    <form method="post" asp-action="PostUserAndImage" enctype="multipart/form-data">
        <input id="Text1" type="text" asp-for="IdUser" />
        <input id="Text1" type="text" asp-for="Name" />
    
        <input id="File1" type="file" name="file" />
        <input id="Submit1" type="submit" value="submit" />
    </form>
    

    Action:

                [HttpPost]
                public async Task<ActionResult<User>> PostUserAndImage(User user, IFormFile file)
                {
                    if (string.IsNullOrWhiteSpace(_env.WebRootPath))
                    {
                        _env.WebRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
                    }
        
                    if (user != null)
                    {
                        _context.User.Add(user);
                        var users = Path.Combine(_env.WebRootPath, "uploads", user.Name);
                        if (!Directory.Exists(users)) Directory.CreateDirectory(users);
                        if (file.Length > 0)
                        {
                            using (var fileStream = new FileStream(Path.Combine(users, file.FileName), FileMode.Create))
                            {
                                await file.CopyToAsync(fileStream);
                            }
                        }
                        await _context.SaveChangesAsync();
                    } 
                   
                     return CreatedAtAction("GetUser", new { id = user.IdUser }, user);
                }
    

    Here is the test result:

    enter image description here