5

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

安排删除超过 1 天/8 小时的文件的最佳方式是什么?最好在 asp.net 应用程序本身...

4

8 回答 8

6

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

// 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 小时。如果有人感兴趣,我会在这里发布。这是我的新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();
            }
        });
    }
}
于 2010-05-17T12:22:46.273 回答
1

最好的方法是创建一个批处理文件,由 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)

}

}

请注意,您也可以在 pageLoad 调用此类,它不会影响处理时间,因为处理在另一个线程中。只需删除 do-while 和 Thread.Join()。

于 2010-05-18T18:49:10.187 回答
1

尝试使用Path.GetTempPath(). 它会给你一个 Windows 临时文件夹的路径。然后由windows来清理:)

您可以在此处阅读有关该方法的更多信息http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx

于 2010-05-14T09:25:11.900 回答
0

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

于 2010-05-14T09:46:08.083 回答
0

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

    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 | 如何:从缓存中删除项目时通知应用程序

于 2012-04-25T14:22:28.387 回答
0

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

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

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

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

于 2010-05-17T14:15:00.973 回答
0

在 Appication_Start 上创建一个计时器,并安排计时器每 1 小时调用一次方法,并刷新超过 8 小时或 1 天或您需要的任何持续时间的文件。

于 2010-05-17T12:25:54.363 回答
0
    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.
        }
    }
于 2010-05-17T14:44:26.423 回答