Search code examples
c#asp.netasp.net-core-mvciis-10

ASP.NET Core 3.1 MVC download file not found until IIS app pool recycle or run website from localhost


I am making an ASP.NET Core 3.1 MVC with Entity Framework website on a Microsoft server running IIS 10 with basic user file upload and download functions. I can upload files to the _webHostEnvironment.WebRootPath from the web but when I try to download them it cannot find them. However, if I recycle the app pool I can download the file (I can also download it from the web after accessing the website on localhost on the server).

Here is the code for when I upload the file:

string uniqueFileName = null;
if (model.Data != null)
{
    string uploadsFolder = Path.Combine(_webHostEnvironment.WebRootPath, "images");
    uniqueFileName = Guid.NewGuid().ToString() + "_" + model.Data.FileName;
    string filePath = Path.Combine(uploadsFolder, uniqueFileName);
    model.Data.CopyTo(new FileStream(filePath, FileMode.Create));
}

Here is the code for when I download it:

public FileResult DownloadData(string fileName, string tempAddCode, string patientName)
{
    byte[] fileBytes = System.IO.File.ReadAllBytes(Path.Combine(_webHostEnvironment.WebRootPath, "images") + "\\" + fileName);
    var dataStream = new MemoryStream(fileBytes);
    return new FileStreamResult(dataStream, new MediaTypeHeaderValue("application/pdf"))
    {
        FileDownloadName = patientName.ToLower().Replace(" ", "_") + ".pdf"
    };
}

What is going on? Why would recycling the app pool fix this? Am I saving these user-uploaded files to the wrong location and ASP.NET is doing some sort of caching thing? I'd love any help finding a solution! Thanks.


Solution

  • With this line you open file stream and never close it.

    model.Data.CopyTo(new FileStream(filePath, FileMode.Create));
    

    Make sure you always dispose your streams, so files don't stay locked. Use code below to properly copy stream to file

    using (var fs = new FileStream(filePath, FileMode.Create))
    {
        model.Data.CopyTo(fs);
    }