2

I'm working on an ASP.NET Core 5 project. I have this action method:

public async Task<IActionResult> CreateV3EnterCheckFile(IFormFile MarksFile)
{
    var filesCount = Directory.GetFiles("Uploads").Length;

    string path = Path.Combine("Uploads", filesCount + 1 + ".xlsx");

    await MarksFile.SaveToAsync(path);

    var xlImporter = new XLImporter();
    var importedData = await xlImporter.ImportSheetAsync(path, 0);

    var r = (from x in importedData select new { ID = x[0], StudentId = x[1] }).ToList();

    System.IO.File.Delete(path);

    return View();
}

I tried to get IFormFile uploaded file by the user to save it on the server and querying it using one of my projects (that uses LinqToExcel library).

I am querying the data and everything is perfect I still have just one problem it is this line of code:

System.IO.File.Delete(path);

It throws an exception and the message is I can't delete that file because it is still being used by another process.

I'm very sure that the process is related to the LinqToExcel library.

More details :

SaveToAsync is an extension method created by me that is its definition

 public static Task SaveToAsync(this IFormFile file, string pathToSaveTo)
        {
            return Task.Factory.StartNew(() =>
            {
                using (Stream fileStream = File.Open(pathToSaveTo, FileMode.Create, FileAccess.ReadWrite, FileShare.None))
                {
                    file.CopyTo(fileStream);
                }
            });
        }

Please - is there any way or method or solution to delete this file even if it is being used by another process?

Massive thanks in advance.

JOCKH
  • 339
  • 4
  • 15
  • You should be sure which process is using your file instead of guessing. Forcing the delete feels like a workaround – RoQuOTriX Aug 07 '21 at 10:12
  • Ok can you provide me a method to know which process exactly use the file ? – JOCKH Aug 07 '21 at 10:15
  • I think you can use the handle.exe of windows to find it out. Maybe also parse the output from your program suggested in this question: https://stackoverflow.com/questions/317071/how-do-i-find-out-which-process-is-locking-a-file-using-net – RoQuOTriX Aug 07 '21 at 10:18

2 Answers2

1

Based on the source code of ExcelQueryFactory (https://github.com/paulyoder/LinqToExcel/blob/master/src/LinqToExcel/ExcelQueryFactory.cs) I would try the following:

  • ExcelQueryFactory has a ReadOnly Property. For read only access (if applicable) I would set it to true when creating the instance.
  • More important: IExcelQueryFactory implements IDisposable, so you can (should) use a using block:
using (var excelFile = new ExcelQueryFactory(pathToExcelFile) {ReadOnly = true})
{
    // Do your work.
}

Of course you can use using var ..., but if you need a more reduced scope, the "old" using syntax allows more control.

Michael
  • 1,166
  • 5
  • 4
  • Hmm, instead of creating a new Task in SaveToAsync you can use *await file.CopyToAsync()*. Try to delete the file after calling MarksFile.SaveToAsync(). This should be possible. – Michael Aug 07 '21 at 11:05
  • I tried to delete the file after saving and deleted fine – JOCKH Aug 07 '21 at 13:28
1

I assumed that your Uploads folder is under webroot.

You can try this:-

 public YourControllerName(IHostingEnvironment he) //input parameter
        {
            
            _he = he;
        }

public async Task<IActionResult> CreateV3EnterCheckFile(IFormFile MarksFile)
{
try 
{ 
    var filesCount = Directory.GetFiles("Uploads").Length;
    
    string contentRootPath = _he.ContentRootPath;

    string path = Path.Combine(contentRootPath +"\\Uploads", filesCount + 1 + ".xlsx");
   

    await MarksFile.SaveToAsync(path);

    var xlImporter = new XLImporter();
    var importedData = await xlImporter.ImportSheetAsync(path, 0);

    var r = (from x in importedData select new { ID = x[0], StudentId = x[1] }).ToList();

    //System.IO.File.Delete(path);

   if (File.Exists(path))
    { 
        File.Delete(path);
    }
    else
    {
        Debug.WriteLine("File does not exist.");
    } 

    return View();
}  

 catch(Exception e) 
 { 
     Console.WriteLine(e); 
 }

Or you can try another process:-

try
{
 System.GC.Collect(); 
 System.GC.WaitForPendingFinalizers(); 
 System.IO.File.Delete(path);
}
catch(Exception e){
}
}

Or this:-

 if (System.IO.File.Exists(path))
        {
            try
            {
                System.GC.Collect();
                System.GC.WaitForPendingFinalizers();
                System.IO.File.Delete(path);

            }
            catch (Exception e) { }
        }

it should resolve your issue I hope. by the way, if your Upload folder is not under the webroot path. you can find your path using your process.

Pritom Sarkar
  • 2,154
  • 3
  • 11
  • 26