﻿# ASP.NET 如何將檔案寫入到網路芳鄰的分享目錄

我們在使用 Webfarm 架構建置網站時，有許多要注意的地方，我想最麻煩的地方就是如何將使用者上傳的檔案同步到每一台主機！

因為使用者每次 Request 到 Webfarm 的主機時，不一定每次都會連線到同一台 WEB 主機，所以在執行檔案上傳時，一定不能儲存到「本機」路徑，因為你上傳到其中一台，另一台就讀不到。

一般來說會有兩種作法：

1.  將檔案或文件全部都儲存到資料庫中。
    
2.  將檔案或文件儲存到一個共享的資料夾中。
    
    這種作法是這樣的：
    
    1.  假設我們有 4 台 WEB 主機，分別命名為 `WEB1`, `WEB2`, `WEB3`, `WEB4`。
    2.  共用的檔案統一儲存在 `WEB4` 主機 （也可以在另一台 File Server ）
    3.  其 `WEB1` ... `WEB4` 的 IIS 都設定一組虛擬目錄 `Files`，並設定對應到 `\\WEB4\ShareFolder` 分享目錄中，並在 IIS 設定登入到 `WEB4` 主機的帳號、密碼。
    4.  然後 `WEB1` ... `WEB4` 的 IIS 就可以用 `http://WEB4/Files/` 讀取 `\\WEB4\ShareFolder` 分享目錄中的檔案了！
    
    不過這時問題來了！
    
    由於 ASP.NET 在運行的時候，是採用 `ASPNET` (IIS5) 或 `NETWORK SERVICE` (IIS6) 身份在執行的，因此並無權限將檔案讀取或寫入到網路芳鄰的 Share Folder 中。
    
    因為透過 IIS 是可以讀的到檔案的，但是透過 ASP.NET 卻無法正確的取得檔案！使用 `System.IO.File.ReadAllText(filename)` 讀取檔案內容時，就會發生 Exception！甚至連 `File.Exists(filename)` 都無法檢查檔案是否存在！
    
    這很有可能會讓 .NET 新手誤以為是 .NET 的 Bug !! 其實 .NET Security 何其重要，希望各位還是抽空多瞭解相關的觀念！
    
    > 備註：我們常用的 `Server.MapPath("~/Files/a.txt")` 套用在這種「虛擬目錄」時，會將檔案路徑替換成 `\\WEB4\ShareFolder\a.txt`
    

接下來，我分享我個人的 Best Practice，這個環境是建立在沒有 AD 的情況下，如果主機群有建立 AD 環境會簡單很多：

**環境說明：**

-   四台 WEB 主機 （ 沒有 AD 環境 ）
    -   主機名稱為 WEB1 ... WEB4
-   一台 File 主機
    -   主機名稱為 File1

**設定步驟：**

1.  新增一個共用的使用者到「 File 主機」與「每一台WEB主機」，每台主機的帳號、密碼都要一樣
    
    -   帳號：ImpersonateUser
    -   密碼：KesTa8ru
2.  在 File 主機新增分享目錄
    
    分享名稱為 `Files`
    
    假設實際目錄路徑為 `D:\Files`
    
3.  修改目錄權限 ( File 主機 )
    
    -   `D:\Files`
        
        ImpersonateUser 可讀取、可寫入(如果需要上傳檔案的話就要開放寫入)
        
    -   `分享目錄權限`
        
        ImpersonateUser 可讀取、可寫入(如果需要上傳檔案的話就要開放寫入)
        
4.  修改目錄權限 ( 所有 WEB 主機 )
    
    -   `C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files`
        
        ImpersonateUser 可讀取、可寫入
        
        > 說明: 因為 Web Application 等一下會設定用 ImpersonateUser 的身分執行，這會造成 ASP.NET 無法將動態編譯的程式碼儲存在這個目錄，所以必須修改這個目錄的權限。
        
    -   `Web Application 所在的目錄`
        
        ImpersonateUser 可讀取
        
5.  確認 IIS 的虛擬目錄設定
    
    -   目錄名稱：`Files`
    -   目的位址：`\\File1\Files`
    -   登入帳號：`ImpersonateUser`
    -   登入密碼：`KesTa8ru`
6.  修改網站的 web.config
    
    在 `<system.web>` 底下新增 `<identity>` 設定，讓網站用 `ImpersonateUser` 的身份執行！
    
    ```xml
    <identity impersonate="true" userName="ImpersonateUser" password="KesTa8ru" />
    ```
    

只要以上六個步驟就可以完成 Webfarm 的架構設定! 但這只有解決檔案權限的問題而已，還有許多其他的開發細節以後有時間再談。
