代码之家  ›  专栏  ›  技术社区  ›  Stefan Steiger Marco van de Voort

ASP.NET计划删除临时文件

  •  4
  • Stefan Steiger Marco van de Voort  · 技术社区  · 15 年前

    问题:我有一个ASP.NET应用程序,它创建临时PDF文件(供用户下载)。 现在,许多用户在许多天内可以创建许多PDF,这需要很大的磁盘空间。

    计划删除超过1天/8小时的文件的最佳方法是什么? 最好是在ASP.NET应用程序中…

    8 回复  |  直到 14 年前
        1
  •  5
  •   Fredrik Johansson    14 年前

    对于需要创建的每个临时文件,在会话中记下文件名:

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

    接下来,将以下清理代码添加到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>
    

    更新 :我现在准确地使用了一种新的(改进的)方法。新的方法包括httpruntime.cache和检查文件是否超过8小时。如果有人感兴趣,我会把它贴在这里。这是我的新 全球ASC.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();
                }
            });
        }
    }
    
        2
  •  1
  •   Oskar Kjellin    15 年前

    试用使用 Path.GetTempPath() . 它将为您提供Windows临时文件夹的路径。然后由Windows来清理:)

    你可以在这里了解更多关于这个方法的信息 http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx

        3
  •  1
  •   Chuck Norris Rohidas Kadam    14 年前

    最好的方法是创建一个批处理文件,该文件由Windows任务计划程序按所需的时间间隔调用。

    可以使用上面的类创建Windows服务

    public class CleanUpBot
    {
    
    public bool KeepAlive;
    
    private Thread _cleanUpThread;
    
    public void Run()
    {
    
    _cleanUpThread = new Thread(StartCleanUp);
    
    }
    
    private void StartCleanUp()
    {
    
    do
    
    {
    
    // HERE THE LOGIC FOR DELETE FILES
    
    _cleanUpThread.Join(TIME_IN_MILLISECOND);
    
    }while(KeepAlive)
    
    }
    
    }
    

    注意,您也可以在页面加载时调用这个类,它不会影响处理时间,因为处理在另一个线程中。只需移除do while和thread.join()。

        4
  •  0
  •   Jakob Gade    15 年前

    如何存储文件?如果可能,您可以使用一个简单的解决方案,其中所有文件都存储在以当前日期和时间命名的文件夹中。
    然后创建一个简单的页面或httphandler来删除旧文件夹。您可以使用Windows调度或其他cron作业每隔一段时间调用此页。

        5
  •  0
  •   this. __curious_geek    15 年前

    在应用程序启动时创建一个计时器,并安排该计时器每隔1小时调用一个方法,并刷新8小时或1天以上的文件或需要的任何持续时间。

        6
  •  0
  •   War    15 年前

    我有点同意德克在回答中所说的话。

    这个想法是,您将文件放到的临时文件夹是一个固定的已知位置,但是我略有不同…

    1. 每次创建文件时,将文件名添加到会话对象中的列表中(假设没有数千个文件,如果该列表命中给定的cap,则执行下一位操作)。

    2. 会话结束时,应在global.asax中引发会话结束事件。迭代列表中的所有文件并删除它们。

        7
  •  0
  •   Joop    15 年前
        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
                }
            }
        }
    

    上面的代码将删除temp目录中8小时前创建或修改的文件。

    不过,我建议使用另一种方法。正如Fredrik Johansson建议的那样,您可以在会话结束时删除用户创建的文件。更好的方法是根据临时目录中用户的会话ID使用一个额外的目录。当会话结束时,只需删除为用户创建的目录。

        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.
            }
        }
    
        8
  •  0
  •   Tim Abell    14 年前

    使用缓存到期通知触发文件删除:

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

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

    推荐文章