ASP.NET Расписание удаления временных файлов - PullRequest
4 голосов
/ 14 мая 2010

Вопрос: у меня есть приложение ASP.NET, которое создает временные файлы PDF (для загрузки пользователем) Теперь многие пользователи в течение многих дней могут создавать множество PDF-файлов, которые занимают много места на диске.

Как лучше всего запланировать удаление файлов старше 1 дня / 8 часов? Желательно в самом приложении asp.net ...

Ответы [ 8 ]

5 голосов
/ 17 мая 2010

Для каждого временного файла, который вам нужно создать, запишите имя файла в сеансе:

// 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();
            }
        });
    }
}
1 голос
/ 18 мая 2010

Лучший способ - создать пакетный файл, который будет вызываться планировщиком задач Windows один раз в нужный интервал.

OR

вы можете создать службу 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 ().

1 голос
/ 14 мая 2010

Попробуйте использовать Path.GetTempPath(). Это даст вам путь к временной папке Windows. Тогда будет до окон убирать:)

Подробнее о методе можно прочитать здесь http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx

0 голосов
/ 25 апреля 2012

Используйте уведомление об истечении срока действия кэша для запуска удаления файла:

    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 | Как: уведомить приложение об удалении элемента из кэша

0 голосов
/ 17 мая 2010
    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
            }
        }
    }

Приведенный выше код удалит файлы из временного каталога, которые были созданы или изменены более 8 часов назад.

Однако я бы предложил использовать другой подход. Как предложил Фредрик Йоханссон, вы можете удалить файлы, созданные пользователем, когда сессия завершится. Лучше работать с дополнительным каталогом на основе идентификатора сеанса пользователя во временном каталоге. Когда сеанс заканчивается, вы просто удаляете каталог, созданный для пользователя.

    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.
        }
    }
0 голосов
/ 17 мая 2010

Я вроде согласен с тем, что сказано в ответе Дирка.

Идея заключается в том, что временная папка, в которую вы перетаскиваете файлы, является фиксированным известным местом, однако я немного различаюсь ...

  1. Каждый раз, когда файл создается, добавьте имя файла в список в объекте сеанса (при условии, что нет тысяч, если есть, когда этот список достигает заданного предела, сделайте следующий бит)

  2. когда сеанс завершается, в global.asax должно вызываться событие Session_End. Переберите все файлы в списке и удалите их.

0 голосов
/ 17 мая 2010

Создайте таймер на Appication_Start и запланируйте таймер для вызова метода каждые 1 час и сбрасывайте файлы старше 8 часов или 1 дня или любой другой необходимой вам длительности.

0 голосов
/ 14 мая 2010

Как вы храните файлы? Если возможно, вы можете просто пойти с простым решением, где все файлы хранятся в папке, названной в честь текущей даты и времени.
Затем создайте простую страницу или httphandler, который удалит старые папки. Вы можете вызывать эту страницу через определенные промежутки времени, используя расписание Windows или другое задание cron.

...