2010-05-14 27 views
4

問題:我有一個ASP.NET應用程序創建臨時PDF文件(供用戶下載)。 現在,很多用戶在很多天都可以創建很多PDF文件,這會佔用大量的磁盤空間。ASP.NET日程安排刪除臨時文件

安排刪除超過1天/ 8小時的文件的最佳方式是什麼? 最好在asp.net應用程序本身...

回答

4

對於您需要創建,請記下會議的文件名的每個臨時文件:

// 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> 

UPDATE:我現在正在使用一種比上面描述的方法更新的(改進的)方法。新的包含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

我認爲根據用戶的臨時目錄或ASP.NET用戶擁有寫權限的其他目錄中的用戶的會話ID創建目錄會更容易。當會話結束時,只需根據會話ID刪除用戶的整個目錄。 – Joop 2010-05-17 14:20:16

+0

我會去參加sessionid文件夾。 – 2010-05-19 06:58:39

+1

如果會話保存在內存中,而不是永久保存到持久會話存儲中,那麼當您有應用程序回收時,可能會泄漏文件。你會失去你的內存列表。 – 2012-03-13 14:20:26

1

嘗試使用Path.GetTempPath()。它會給你一個Windows臨時文件夾的路徑。然後,它會達到窗戶清理:)

您可以在此處詳細瞭解該方法http://msdn.microsoft.com/en-us/library/system.io.path.gettemppath.aspx

+0

你需要給寫入臨時asp.net工作進程/應用程序池的許可? – 2010-05-14 13:02:35

+0

@James不知道,也許 – 2010-05-14 14:02:34

+0

@詹姆斯:是的,絕對(Vista +)。此外,ASP.NET用戶需要對temp的讀取權限,下載文件和文件枚舉權限以獲取目錄中的文件列表。 – 2010-05-14 15:20:10

0

如何存儲的文件?如果可能,您可以使用簡單的解決方案,其中所有文件都存儲在以當前日期和時間命名的文件夾中。
然後創建一個簡單的頁面或httphandler,它將刪除舊的文件夾。您可以使用Windows時間表或其他cron作業定期調用此頁面。

+0

在當前日期和時間之後不需要命名文件。文件名是一個guid.tostring +「.pdf」。您可以從文件屬性中讀取文件創建/修改日期。是的,他們都在同一個文件夾中。 – 2010-05-14 15:22:34

0

上Appication_Start創建一個定時器,並安排定時器呼籲每1小時方法並刷新文件年長超過8小時或1天或任何時間你需要。

0

我有點贊同dirk在回答中所說的話。

的想法是,在其中您刪除文件到臨時文件夾是一個固定的已知位置,但是我稍微不同......

  1. 每一個文件被創建的文件名添加到列表中的時間會話對象(假設沒有成千上萬,當這個列表遇到給定上限時做下一位)

  2. 當會話結束Session_End事件時應該引發global.asax應該引發。迭代列表中的所有文件並刪除它們。

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

上述代碼將刪除在被創建或修改時間超過8小時前的臨時目錄中的文件。

但是我會建議使用另一種方法。正如Fredrik Johansson所建議的那樣,您可以在會話結束時刪除用戶創建的文件。更好的方法是使用基於temp目錄中用戶的會話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. 
     } 
    } 
1

最好的方法是創建一個批處理文件,它將由Windows任務調度程序以您希望的間隔調用一個。

OR

你可以創建一個類窗口服務上面

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()。

+0

這些正是我試圖避免的事情。首先,Windows調度程序從來不是一個好主意(在許可鎖定的環境中,比如在我們的客戶中,它永遠不會工作),第二個Windows服務需要安裝程序,我做過一次,並且誠實地說,收集的體驗正是我爲什麼不想再做一次。 – 2010-05-19 06:55:30

+0

如果您對Windows安裝程序服務不熟悉,則可以在pageLoad no處調用CleanUpBot類。在第一行放置像這樣的東西... CleanUp();並且在該方法.... 私人布爾清理() { 嘗試 { 變種lastCleanUp = DateTime.Parse(應用[ 「LastCleanUp」]的ToString()); } catch(Exception) { Application [「LastCleanUp」] = DateTime.Now; } finally { new CleanUpBot()。Run(lastCleanUp); } } – 2010-05-19 20:48:03

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 | How to: Notify an Application When an Item Is Removed from the Cache