Introduction/Background
Hello again!
Two days ago, I was working on a complex ASP.NET upload module. (I was actually basing my work on this half completed upload module - http://darrenjohnstone.net.)
I changed the code so it will automatically find out what the Windows Temp folder is, in number of ways so it will have a failsafe, and then upload files to a subfolder there, and give it a random name from a GUID. So far - so good.
Now the thing that bugged me all along the way is - what the heck will happen to the temp files?
You see the thing is that, Windows do not take care of the Temp folder in any way. It will never delete files by itself. An application that's making things dirty in the temp has to clean it after itself afterwards.
So I provided a "MoveTo" function to move the file to the destination location (not copy, that will be a waste of resources). This way, if the file is handled, nothing is left in the temp. But what if no code handled the uploaded files? Or there was an error? The file can be handled or can not be handled - anywhere during the current context, and I have no way to track/control what happens.
Then I came up with a simple solution: A deleter class.
It is actually very simple:
- It contains a full local path to a file which we want to delete.
- It implements a proper dispose pattern, which will dispose the file itself.
- It implements a method to "Cancel" the deletion.
OK, I'm going to write down the code that I wrote, but I'm not going to write anything regarding the upload mechanism because it is an unrelated issue, and this "deleter" class is relevant to many other situations.
Using the Code
This is 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)
{
}
try
{
DeleteFile();
}
catch { }
}
}
If you are not familiar with .NET's disposing mechanism, you better start researching it a bit, so you'll understand what's going on here. (It is actually very simple.)
What happens here is that only when this class is disposed, it tries to delete the file.
So, if there's a file that I created that is temporary and I want to get rid of it later on, I will create an instance of this class like this:
deleter = new TemporaryFileDeleter("C:\Windows\Temp\1234.dat");
But if I decided to keep the file (or prevent it from trying to delete a file that I have already moved, in case of a "MoveTo" function), I can call: deleter.DoNotDelete()
.
If I'll use again the example of a file upload module, then it goes like this: I'm creating a separate "File processor" class for each FileUpload
(derived) control, and that class tries to create the temp file and stream data inside the file. But right after it creates the file, long before it starts streaming in, it will create an instance of the TemporaryFileDeleter
and assign it as a member variable to the processor class. The garbage collector of .NET framework will dare to destroy/dispose the processor class only after the FileUpload
control got destroyed, which means when the Request is finished. And only then it will also try to dispose the TemporaryFileDeleter
class and actually delete the file.
If anywhere along the way something goes really wrong, it's still OK, because even if IIS terminates unexpectedly, it will still try to dispose objects and kill that file! I made some tests and caused IIS to crash - the temp files still got deleted.
Note: Even if you are not seeing the file getting deleted immediately, it will happen probably in the next 2-3 minutes. The garbage collector works in mysterious ways (smart ways), and it will kill the file when it wants to.
Points of Interest
A point of interest, or a point of driving you mad, is the fact that Microsoft never implemented any garbage collector for Windows... Why do I always have to clean up after other applications and after Windows itself? It will be very simple to decide that Windows will clean up files from Temp folder, on each restart (or maybe on a second restart to allow legacy support for setup applications which keep temp files until next restart). Maybe even a way to "register" a temp file with Windows, for deletion later, with some set of rules. But no! Haven't heard of such thing...
I hope I helped someone!
History
Nothing yet...