Web 伺服器 (Server A) 接收用戶上傳檔案,但因存儲空間、備份策略或架構隔離,需將檔案實際寫入獨立的檔案伺服器 (Server B)。最常見且成本最低的方案是利用 Windows 檔案共享 (SMB/CIFS) 配合身分模擬 (Impersonation)。
[Client] → [Web Server A (IIS)] → (SMB Share) → [File Server B]
│
└─ 需以具備 B 寫入權限的網域/本地帳號執行寫入動作
D:\FileShare) → 右鍵「屬性」→「共用」→「進階共用」→ 勾選「共用此資料夾」→「權限」→ 新增帳號 DocShareUser → 給予「讀取/寫入」。DocShareUser,設定強式密碼,加入「Users」群組即可 (無需管理員權限)。在 A 上同樣建立 DocShareUser,**使用者名稱與密碼必須與 B 完全一致** (若為網域環境則直接使用網域帳號)。此為 NTLM 驗證自動匹配的關鍵。
FileShare;實體路徑: \\ServerB\FileShare (UNC 格式)。DocShareUser 及密碼 → 「測試設定」皆綠燈。
<system.web>
<identity impersonate="true" userName="DocShareUser" password="YourPassword" />
</system.web>
⚠️ **副作用**:整個 ASP.NET 應用程式將以此身分執行,可能導致存取資料庫、登入系統等原本依賴 `ApplicationPoolIdentity` 的功能失效。另需額外授權 C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files 給該帳號讀寫權限,否則編譯臨時檔案會失敗。

protected void Application_Start()
{
// 啟動時建立與 B 的 SMB 會話,憑證快取於 LSA,後續存取自動使用
string cmd = @"net use \\ServerB\FileShare ""Password"" /user:""DocShareUser""";
System.Diagnostics.Process.Start("cmd.exe", $"/c {cmd}").WaitForExit();
}
優點:不改變應用程式執行身分,僅建立 SMB 會話憑證;重啟 IIS 後需重新執行,可寫入 Windows 排程器或服務確保持久。
string virtualPath = "~/FileShare/Uploads/"; // 虛擬目錄別名
string physicalPath = Server.MapPath(virtualPath); // 自動解析為 \\ServerB\FileShare\Uploads\
string savePath = Path.Combine(physicalPath, fileName);
using (FileStream fs = new FileStream(savePath, FileMode.Create, FileAccess.Write))
{
await uploadedFile.InputStream.CopyToAsync(fs);
}
IIS 預設限制 4MB,修改 Web.config:
<system.web>
<httpRuntime maxRequestLength="102400" executionTimeout="300" /> <!-- 100MB, 5分鐘 -->
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="104857600" /> <!-- 100MB (bytes) -->
</requestFiltering>
</security>
</system.webServer>
| 現象 | 可能原因 | 解決 |
|---|---|---|
| 401/403 Unauthorized | 帳號密碼不一致、B 未授權該帳號、防火牆攔截 | 逐項核對帳號、共用權限、NTFS 權限、防火牆 445 埠 |
| 「找不到網路路徑」 | UNC 路徑錯誤、DNS 解析失敗、SMB 服務未啟動 | 用 `ping ServerB`、`net view \\ServerB` 測試連通性 |
| 寫入成功但檔案 0 bytes | NTFS 權限僅有「列出資料夾/讀取資料」無「建立檔案/寫入資料」 | 在 B 資料夾「安全性」頁籤給予 DocShareUser「修改」權限 |
| ApplicationPoolIdentity 無法存取共享 | 未建立信任關係 (步驟 4) | 執行 `net use` 或設定 `impersonate="true"` |
跨伺服器檔案寫入的核心在於 **身分一致性** 與 **最小權限原則**。推薦採用「虛擬目錄 + Global.asax net use」組合:設定簡單、不汙染應用程式身分、易於維護。若規模較大或需高可用,建議改用分散式檔案系統 (DFS)、對象存儲 (MinIO/S3) 或專用檔案服務 API。