寫網站時有時需要產生暫存檔,過去我慣用的做法是透過System.IO.Path.GetTempPath(),將暫存檔寫入Windows系統暫存資料夾,如意算盤是暫存資料夾本來就是放暫存檔的地方,而Windows有機制可在磁碟空間不足時刪除暫存檔釋放空間,如果檔案沒有機密或敏感性,放在暫存資料夾基本上可以Fire and Forget,用過就放著不管,很省事。
後來幾次部署經驗告訴我,「ASP.NET程式不一定有寫入暫存資料夾的權限」(登楞!)。針對Temp資料夾開放ASP.NET寫入權限是一種解法,但每個ASP.NET應用程式的執行身分不同,搞下來Temp資料夾需維護一堆權限有點複雜。相形之下,App_Data隸屬各ASP.NET應用程式,可部署時一併設定權限統一管理,相對簡便。(註:適合放暫存檔是因為App_Data具有隱身特性,請不要將暫存檔放在一般網站目錄下,以免被使用者不當存取)
但暫存檔放App_Data就不像系統暫存資料夾可以靠Windows機制回收空間,得自行清理過期暫存檔。最直覺做法是寫個排程每天定時刪檔,但最近我想出另一個更省事的做法-取得暫存目錄時自動清理過期檔案。程式範例如下,分享兼請大家Code Review:P
//記憶上次清理執行日期 staticstring lastAttTempCleanDate = null; //非同步鎖定 staticobject cleanLock = new Object(); staticstring GetTempPath() { //使用App_Data暫存檔案,避免ASPX沒有寫入系統TEMP權限 string tempPath = Path.Combine( HttpContext.Current.Server.MapPath("~/App_Data"), "UploadAtts"); //若目錄不存在,建立之 Directory.CreateDirectory(tempPath); //每次啟動網站或每天清理一次過期Cache string todayDate = DateTime.Today.ToString("yyyyMMdd"); //防止多執行緒同時觸發 lock (cleanLock) { //比對上次執行日期,原則上每天只執行一次 if (todayDate != lastAttTempCleanDate) { //先儲存執行日期記錄,避免重複執行 lastAttTempCleanDate = todayDate; //另開Thread執行刪除,以免卡住目前的暫存作業 Task.Factory.StartNew(() => { //決定逾期判斷基準 DateTime expireTime = DateTime.Today; foreach (var file in Directory.GetFiles(tempPath)) { //若檔案建立時間早於今天,刪除之 if (File.GetCreationTime(file).CompareTo(expireTime) == -1) { File.Delete(file); } } }); } } return tempPath; } |