【问题标题】:How to force delete a file used by another process in Asp.net core如何强制删除 Asp.net 核心中另一个进程使用的文件
【发布时间】:2021-08-07 10:08:42
【问题描述】:

我正在开发一个 ASP.NET Core 5 项目。我有这个动作方法:

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

我尝试获取用户上传的IFormFile 文件以将其保存在服务器上并使用我的一个项目(使用LinqToExcel 库)查询它。

我正在查询数据,一切都很完美我还有一个问题,就是这行代码:

System.IO.File.Delete(path);

它引发异常,消息是我无法删除该文件,因为它仍在被另一个进程使用。

我很确定这个过程与LinqToExcel库有关。

更多详情:

SaveToAsync是我自己创建的扩展方法就是它的定义

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

请 - 是否有任何方法、方法或解决方案可以删除此文件,即使它正在被另一个进程使用?

提前非常感谢。

【问题讨论】:

  • 您应该确定哪个进程正在使用您的文件,而不是猜测。强制删除感觉像是一种解决方法
  • 好的,你能给我一个方法来知道哪个进程确切地使用了这个文件吗?
  • 我想你可以使用windows的handle.exe来查找。也许还可以解析这个问题中建议的程序的输出:stackoverflow.com/questions/317071/…

标签: c# asp.net-core io .net-5 linq-to-excel


【解决方案1】:

我假设您的Uploads 文件夹在webroot 下。

你可以试试这个:-

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

或者你可以尝试另一个过程:-

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

或者这个:-

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

            }
            catch (Exception e) { }
        }

我希望它应该可以解决您的问题。顺便说一句,如果您的上传文件夹不在 webroot 路径下。您可以使用您的流程找到您的路径。

【讨论】:

    【解决方案2】:

    基于 ExcelQueryFactory (https://github.com/paulyoder/LinqToExcel/blob/master/src/LinqToExcel/ExcelQueryFactory.cs) 的源代码,我会尝试以下操作:

    • ExcelQueryFactory 具有只读属性。对于只读访问(如果适用),我会在创建实例时将其设置为 true。
    • 更重要的是:IExcelQueryFactory 实现了 IDisposable,因此您可以(应该)使用 using 块:
    using (var excelFile = new ExcelQueryFactory(pathToExcelFile) {ReadOnly = true})
    {
        // Do your work.
    }
    

    当然你可以使用using var ...,但是如果你需要更小的范围,“旧”的使用语法允许更多的控制。

    【讨论】:

    • 嗯,您可以使用 await file.CopyToAsync(),而不是在 SaveToAsync 中创建新任务。调用 MarksFile.SaveToAsync() 后尝试删除文件。这应该是可能的。
    • 保存后我尝试删除文件,删除正常
    猜你喜欢
    • 2012-10-01
    • 2013-05-27
    • 1970-01-01
    • 2011-08-09
    • 2012-10-27
    相关资源
    最近更新 更多