65.9K
CodeProject 正在变化。 阅读更多。
Home

一个处理临时文件的简单技术(提示:Windows 不会自动为您处理)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (7投票s)

2010年5月31日

CPOL

4分钟阅读

viewsIcon

41767

这是一种简单而巧妙的方法,我想出了即使在我忘记它们很久之后也能删除临时文件的方法。

介绍/背景

大家好!

两天前,我正在开发一个复杂的 ASP.NET 上传模块。(实际上,我是在这个未完成的上传模块的基础上进行开发的 - http://darrenjohnstone.net。)

我更改了代码,使其能够自动找出 Windows 临时文件夹的位置,通过多种方式实现故障安全,然后将文件上传到该文件夹的一个子文件夹中,并使用 GUID 为其指定一个随机名称。到目前为止 - 一切都很好。

现在,一直困扰我的是 - 临时文件会发生什么情况?

您要知道,Windows 不会以**任何**方式管理临时文件夹。 它永远不会自行删除文件。 在临时文件中弄脏东西的应用程序必须在事后自行清理。

所以我提供了一个 "MoveTo" 函数,将文件移动到目标位置(而不是复制,这会浪费资源)。 这样,如果文件被处理,就不会在临时文件中留下任何东西。 但是,如果没有代码处理上传的文件怎么办? 或者出现错误? 文件可能会在当前上下文中的任何位置被处理或不被处理,并且我无法跟踪/控制会发生什么。

然后我想出了一个简单的解决方案:一个删除器类。

它实际上非常简单

  1. 它包含要删除的文件的完整本地路径。
  2. 它实现了一个正确的 dispose 模式,它会释放文件本身。
  3. 它实现了一个 "Cancel" 删除的方法。

好的,我将写下我编写的代码,但我不会编写任何关于上传机制的内容,因为它是一个无关的问题,并且这个 "deleter" 类与许多其他情况相关。

Using the Code

这是代码

public class TemporaryFileDeleter : IDisposable 
{
  private string _LocalFilePath;

  public string LocalFilePath
  {
      get { return _LocalFilePath; }
  }

  public TemporaryFileDeleter(string localFilePath)
  {
      _LocalFilePath = localFilePath;
  }

  ~TemporaryFileDeleter()
  {
      Dispose(false);
  }

  public void DeleteFile()
  {
      string path = _LocalFilePath;
      _LocalFilePath = null;
      if (path == null) return;
      System.IO.File.Delete(path);
  }

  public void DoNotDelete()
  {
      _LocalFilePath = null;
  }

  public void Dispose()
  {
      Dispose(true);
      GC.SuppressFinalize(this);
  }

  protected virtual void Dispose(bool disposing)
  {
      if (disposing)
      {
      }
      // Now clean up Native Resources
      try
      { 
          DeleteFile();
      }
      catch { }
  }
}

如果您不熟悉 .NET 的 disposing 机制,最好先研究一下,这样您才能了解这里发生了什么。(它实际上非常简单。)

这里发生的是,只有当这个类被 disposed 时,它才会尝试删除该文件。

所以,如果我创建了一个临时文件,并且我想稍后删除它,我将像这样创建这个类的一个实例

deleter = new TemporaryFileDeleter("C:\Windows\Temp\1234.dat");

但是,如果我决定保留该文件(或者防止它尝试删除我已经移动的文件,以防使用 "MoveTo" 函数),我可以调用: deleter.DoNotDelete()

如果我再次使用文件上传模块的示例,那么它是这样的:我为每个 FileUpload(派生)控件创建一个单独的 "File processor" 类,并且该类尝试创建临时文件并将数据流式传输到文件中。 但是,在创建文件之后,在开始流式传输之前,它将创建 TemporaryFileDeleter 的一个实例,并将其作为成员变量分配给处理器类。.NET 框架的垃圾回收器只会在 FileUpload 控件被销毁后才敢销毁/释放处理器类,这意味着在请求完成后。 只有到那时,它才会尝试释放 TemporaryFileDeleter 类并实际删除该文件。

如果在任何时候出现严重错误,也没关系,因为即使 IIS 意外终止,它仍然会尝试释放对象并杀死该文件! 我做了一些测试并导致 IIS 崩溃 - 临时文件仍然被删除。

注意:即使您没有立即看到文件被删除,它也可能会在接下来的 2-3 分钟内发生。 垃圾回收器以神秘的方式(聪明的方式)工作,它会在它想要的时候杀死该文件。

关注点

一个有趣的点,或者一个让你发疯的点是,微软从未为 Windows 实现任何垃圾回收器... 为什么我总是必须清理其他应用程序和 Windows 自身? 如果决定 Windows 在每次重新启动时(或者可能在第二次重新启动时,以允许旧版支持在下次重新启动之前保留临时文件的安装程序)清理 Temp 文件夹中的文件,这将非常简单。 甚至可以使用一种方法向 Windows "注册" 一个临时文件,以便稍后使用一些规则进行删除。 但是**没有**! 从未听说过这种事情...

希望我能帮助到大家!

历史

还没有...

© . All rights reserved.