在 ASP.NET 開發中,經常需要驗證伺服器端的檔案或目錄是否存在。.NET Framework 提供了 `System.IO.File.Exists` 與 `System.IO.Directory.Exists` 兩個靜態方法,使用簡單且效能良好。本文說明正確用法與路徑處理注意事項。
using System.IO;
string filePath = @"C:\Data\aaa.txt"; // 使用 @ 字串避免跳脫字元問題
if (File.Exists(filePath))
{
// 檔案存在,可進行讀取、複製、刪除等操作
Console.WriteLine("檔案存在:" + filePath);
}
else
{
Console.WriteLine("檔案不存在");
}
string physicalPath = Server.MapPath("~/Uploads/file.txt");
string fullPath = Path.Combine(baseDir, "subfolder", fileName);
using System.IO;
string dirPath = @"C:\WebSites\www.jb51.net";
if (Directory.Exists(dirPath))
{
Console.WriteLine("目錄存在:" + dirPath);
// 可進一步列舉檔案
string[] files = Directory.GetFiles(dirPath, "*.txt");
}
else
{
Console.WriteLine("目錄不存在");
// 如需建立:Directory.CreateDirectory(dirPath);
}
public bool SaveUploadedFile(HttpPostedFileBase postedFile, string relativeFolder)
{
// 1. 轉換為實體路徑
string physicalFolder = Server.MapPath(relativeFolder);
// 2. 確保目錄存在
if (!Directory.Exists(physicalFolder))
{
try
{
Directory.CreateDirectory(physicalFolder);
}
catch (Exception ex)
{
// 記錄錯誤:權限不足、路徑無效等
LogError("建立目錄失敗:" + physicalFolder, ex);
return false;
}
}
// 3. 組合完整檔案路徑
string fileName = Path.GetFileName(postedFile.FileName);
string fullPath = Path.Combine(physicalFolder, fileName);
// 4. 避免覆蓋:檔案存在則重新命名
if (File.Exists(fullPath))
{
string name = Path.GetFileNameWithoutExtension(fileName);
string ext = Path.GetExtension(fileName);
int counter = 1;
while (File.Exists(fullPath))
{
fullPath = Path.Combine(physicalFolder, $"{name}_{counter}{ext}");
counter++;
}
}
// 5. 儲存檔案
try
{
postedFile.SaveAs(fullPath);
return true;
}
catch (Exception ex)
{
LogError("儲存檔案失敗:" + fullPath, ex);
return false;
}
}
| 情境 | 錯誤做法 | 正確做法 |
|---|---|---|
| 路徑字串 | `"C:\Folder\file.txt"` | `@"C:\Folder\file.txt"` 或 `"C:\\Folder\\file.txt"` |
| Web 相對路徑 | 直接使用 `"~/Uploads/"` | `Server.MapPath("~/Uploads/")` |
| 組合路徑 | 字串連接 `folder + "\\" + file` | `Path.Combine(folder, file)` |
| 權限問題 | 不處理例外 | try-catch 捕捉 UnauthorizedAccessException |
| 競爭條件 | 檢查後直接操作 | 操作時再用 try-catch 處理「不存在」例外 |
using System.IO;
// FileInfo / DirectoryInfo 提供更豐富的屬性
var fileInfo = new FileInfo(physicalPath);
if (fileInfo.Exists)
{
long size = fileInfo.Length;
DateTime modified = fileInfo.LastWriteTime;
}
// 非同步檢查(適用於高併發)
// 注意:IO 作業本質同步,通常不需非同步包裝
bool exists = await Task.Run(() => File.Exists(path));
使用 `File.Exists` 與 `Directory.Exists` 是最直接的檢查方式。關鍵在於正確處理路徑轉換(`Server.MapPath`)、路徑組合(`Path.Combine`)與權限例外。實務上建議「嘗試操作並捕捉例外」取代「先檢查再操作」,避免競爭條件。