How to save IFormFile to disk?
Asked Answered
H

3

92

I'm trying to save a file on disk using this piece of code.

IHostingEnvironment _hostingEnvironment;
public ProfileController(IHostingEnvironment hostingEnvironment)
{
   _hostingEnvironment = hostingEnvironment;
}

[HttpPost]
public async Task<IActionResult> Upload(IList<IFormFile> files)
{
    foreach (var file in files)
    {
        var fileName = ContentDispositionHeaderValue
            .Parse(file.ContentDisposition)
            .FileName
            .Trim('"');

        var filePath = _hostingEnvironment.WebRootPath + "\\wwwroot\\" + fileName;
        await file.SaveAsAsync(filePath);
    }
    return View();
}

I was able to replace IApplicationEnvironment with IHostingEnvironment, and ApplicationBasePath with WebRootPath.

It seems like IFormFile doesn't have SaveAsAsync() anymore. How do I save file to disk then?

Hypoderma answered 4/9, 2016 at 22:37 Comment(0)
J
161

A few things have changed since core's release candidates

public class ProfileController : Controller {
    private IWebHostEnvironment _hostingEnvironment;

    public ProfileController(IWebHostEnvironment environment) {
        _hostingEnvironment = environment;
    }

    [HttpPost]
    public async Task<IActionResult> Upload(IList<IFormFile> files) {
        string uploads = Path.Combine(_hostingEnvironment.WebRootPath, "uploads");
        foreach (IFormFile file in files) {
            if (file.Length > 0) {
                string filePath = Path.Combine(uploads, file.FileName);
                using (Stream fileStream = new FileStream(filePath, FileMode.Create)) {
                    await file.CopyToAsync(fileStream);
                }
            }
        }
        return View();
    }
}
Jansen answered 4/9, 2016 at 22:52 Comment(8)
you should not use file.FileName from the user input and directly combine it with path.combine, as this file name could contain routing to subdirectories ("../../") you always need to recheck with e.g. Path.GetFullPath(generatedPath) if the return value is the same as your wanted upload directory. Also the filename from the request is not unique.Mediation
I just get a DirectoryNotFoundException, as filePath points to C:\relative\path rather than ~\relative\path ..Placative
Dont forget to close the filestream.Flagler
@Flagler the using statement will close and dispose of the stream when it goes out of scope.Jansen
In my case file was not getting save unless I called Dispose, probably a code issue.Flagler
Me too. Without that fileStream.Close() it would create the file... but with a filesize of 0. You definitely need to close the stream, not just leave the using to dispose of it.Fistulous
It appears we should use IWebHostEnvironment instead of IHostingEnvironment by nowConsolidation
@Consolidation yes. That is the most recent version. This is a very old post when you look at how frequently the framework has be updated. I have updated the post to reflect current changesJansen
U
4

There are to be further changes in Core 3.0 as IHostingEnvironment is now marked as obsolete.

using Microsoft.Extensions.Hosting;

public class ProfileController  : Controller
{
    private IHostEnvironment _hostingEnvironment;

    public ProfileController(IHostEnvironment environment)
    {
        _hostingEnvironment = environment;
    }
Unquote answered 7/5, 2020 at 15:28 Comment(1)
Don't forget, with the new IHostEnvironment, you need to replace _hostingEnvironment.WebRootPath with _hostingEnvironment.ContentRootPathUltraism
N
1

Thanks for @Nkosi and @Eric Hewett's answers.

Net7 full updated code:


private IHostEnvironment _hostingEnvironment;

 public FilesController(IHostEnvironment hostingEnvironment)
 {
            _hostingEnvironment = hostingEnvironment;
 }

[HttpPost]
[Route("SaveFile")]
public async Task<IActionResult> HtmlToPdf(IFormFile file)
{
  string uploads = Path.Combine(_hostingEnvironment.ContentRootPath, "uploads");
  if (file.Length > 0)
  {
       string filePath = Path.Combine(uploads, file.FileName);
       using (Stream fileStream = new FileStream(filePath, FileMode.Create))
       {
           await  file.CopyToAsync(fileStream);
       }
  }
  return Ok();
}
Neigh answered 10/5, 2023 at 7:35 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.