ASP.NET Schedule deletion of temporary files

2019-02-14 16:38发布

Question: I have an ASP.NET application which creates temporary PDF files (for the user to download). Now, many users over many days can create many PDFs, which take much disk space.

What's the best way to schedule deletion of files older than 1 day/ 8 hours ? Preferably in the asp.net application itselfs...

8条回答
祖国的老花朵
2楼-- · 2019-02-14 17:01

For each temporary file that you need to create, make a note of the filename in the session:

// create temporary file:
string fileName = System.IO.Path.GetTempFileName();
Session[string.Concat("temporaryFile", Guid.NewGuid().ToString("d"))] = fileName;
// TODO: write to file

Next, add the following cleanup code to global.asax:

<%@ Application Language="C#" %>
<script RunAt="server">
    void Session_End(object sender, EventArgs e) {
        // Code that runs when a session ends. 
        // Note: The Session_End event is raised only when the sessionstate mode
        // is set to InProc in the Web.config file. If session mode is set to StateServer 
        // or SQLServer, the event is not raised.

        // remove files that has been uploaded, but not actively 'saved' or 'canceled' by the user
        foreach (string key in Session.Keys) {
            if (key.StartsWith("temporaryFile", StringComparison.OrdinalIgnoreCase)) {
                try {
                    string fileName = (string)Session[key];
                    Session[key] = string.Empty;
                    if ((fileName.Length > 0) && (System.IO.File.Exists(fileName))) {
                        System.IO.File.Delete(fileName);
                    }
                } catch (Exception) { }
            }
        }

    }       
</script>

UPDATE: I'm now accually using a new (improved) method than the one described above. The new one involves HttpRuntime.Cache and checking that the files are older than 8 hours. I'll post it here if anyones interested. Here's my new global.asax.cs:

using System;
using System.Web;
using System.Text;
using System.IO;
using System.Xml;
using System.Web.Caching;

public partial class global : System.Web.HttpApplication {
    protected void Application_Start() {
        RemoveTemporaryFiles();
        RemoveTemporaryFilesSchedule();
    }

    public void RemoveTemporaryFiles() {
        string pathTemp = "d:\\uploads\\";
        if ((pathTemp.Length > 0) && (Directory.Exists(pathTemp))) {
            foreach (string file in Directory.GetFiles(pathTemp)) {
                try {
                    FileInfo fi = new FileInfo(file);
                    if (fi.CreationTime < DateTime.Now.AddHours(-8)) {
                        File.Delete(file);
                    }
                } catch (Exception) { }
            }
        }
    }

    public void RemoveTemporaryFilesSchedule() {
        HttpRuntime.Cache.Insert("RemoveTemporaryFiles", string.Empty, null, DateTime.Now.AddHours(1), Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, delegate(string id, object o, CacheItemRemovedReason cirr) {
            if (id.Equals("RemoveTemporaryFiles", StringComparison.OrdinalIgnoreCase)) {
                RemoveTemporaryFiles();
                RemoveTemporaryFilesSchedule();
            }
        });
    }
}
查看更多
干净又极端
3楼-- · 2019-02-14 17:09

I sort of agree with whats said in the answer by dirk.

The idea being that the temp folder in which you drop the files to is a fixed known location however i differ slightly ...

  1. Each time a file is created add the filename to a list in the session object (assuming there isn't thousands, if there is when this list hits a given cap do the next bit)

  2. when the session ends the Session_End event should be raised in global.asax should be raised. Iterate all the files in the list and remove them.

查看更多
狗以群分
4楼-- · 2019-02-14 17:13

Create a timer on Appication_Start and schedule the timer to call a method on every 1 hours and flush the files older than 8 hours or 1 day or whatever duration you need.

查看更多
我想做一个坏孩纸
5楼-- · 2019-02-14 17:13
    private const string TEMPDIRPATH = @"C:\\mytempdir\";
    private const int DELETEAFTERHOURS = 8;

    private void cleanTempDir()
    {
        foreach (string filePath in Directory.GetFiles(TEMPDIRPATH))
        {
            FileInfo fi = new FileInfo(filePath);
            if (!(fi.LastWriteTime.CompareTo(DateTime.Now.AddHours(DELETEAFTERHOURS * -1)) <= 0)) //created or modified more than x hours ago? if not, continue to the next file
            {
                continue;
            }

            try
            {
                File.Delete(filePath);
            }
            catch (Exception)
            {
                //something happened and the file probably isn't deleted. the next time give it another shot
            }
        }
    }

The code above will remove the files in the temp directory that are created or modified more than 8 hours ago.

However I would suggest to use another approach. As Fredrik Johansson suggested, you can delete the files created by the user when the session ends. Better is to work with an extra directory based on the session ID of the user in you temp directory. When the session ends you simply delete the directory created for the user.

    private const string TEMPDIRPATH = @"C:\\mytempdir\";
    string tempDirUserPath = Path.Combine(TEMPDIRPATH, HttpContext.Current.User.Identity.Name);
    private void removeTempDirUser(string path)
    {
        try
        {
            Directory.Delete(path);
        }
        catch (Exception)
        {
            //an exception occured while deleting the directory.
        }
    }
查看更多
冷血范
6楼-- · 2019-02-14 17:16

Use the cache expiry notification to trigger file deletion:

    private static void DeleteLater(string path)
    {
        HttpContext.Current.Cache.Add(path, path, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 8, 0, 0), CacheItemPriority.NotRemovable, UploadedFileCacheCallback);
    }

    private static void UploadedFileCacheCallback(string key, object value, CacheItemRemovedReason reason)
    {
        var path = (string) value;
        Debug.WriteLine(string.Format("Deleting upladed file '{0}'", path));
        File.Delete(path);
    }

ref: MSDN | How to: Notify an Application When an Item Is Removed from the Cache

查看更多
疯言疯语
7楼-- · 2019-02-14 17:18

Try using Path.GetTempPath(). It will give you a path to a windows temp folder. Then it will be up to windows to clean up :)

You can read more about the method here http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx

查看更多
登录 后发表回答