在 ASP.NET Web Page (Razor) 網站中使用檔案
本文說明如何在 ASP.NET Web Pages (Razor) 網站中讀取、寫入、附加、刪除和上傳檔案。
注意
如果您想要上傳影像並操控影像 (例如翻轉或調整大小),請參閱在 ASP.NET Web Pages 網站中使用影像。
您將學會:
- 如何建立文字檔並將資料寫入其中。
- 如何將資料附加至現有檔案。
- 如何讀取檔案並從中顯示。
- 如何從網站刪除檔案。
- 如何讓使用者上傳一或多個檔案。
以下是本文中介紹的 ASP.NET 程式設計功能:
File
物件,提供管理檔案的方法。FileUpload
協助程式。Path
物件,提供可讓您操控路徑和檔案名稱的方法。教學課程中使用的軟體版本
- ASP.NET Web Pages (Razor) 2
- WebMatrix 2
本教學課程也適用於 WebMatrix 3。
建立文字檔並將資料寫入其中
除了在網站中使用資料庫之外,您也可以使用檔案。 例如,您可以使用文字檔做為儲存網站資料的簡單方法。 (用來儲存資料的文字檔有時稱為「一般檔案」。文字檔的格式可能不同,例如 .txt、.xml 或 .csv (逗號分隔值)。
如果您想要將資料儲存在文字檔中,可以使用 File.WriteAllText
方法來指定要建立的檔案,以及要寫入的資料。 在此程序中,您將建立一個頁面,其中包含一個簡單表單,還有三個 input
元素 (名字、姓氏和電子郵件地址) 和一個提交按鈕。 當使用者提交表單時,您會將使用者的輸入儲存在文字檔中。
建立一個名為 App_Data 的新資料夾 (如果尚未存在的話)。
在網站的根目錄中,建立一個名為 UserData.cshtml 的新檔案。
將現有內容取代如下:
@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.WriteAllText(@dataFile, userData); result = "Information saved."; } } <!DOCTYPE html> <html> <head> <title>Write Data to a File</title> </head> <body> <form id="form1" method="post"> <div> <table> <tr> <td>First Name:</td> <td><input id="FirstName" name="FirstName" type="text" /></td> </tr> <tr> <td>Last Name:</td> <td><input id="LastName" name="LastName" type="text" /></td> </tr> <tr> <td>Email:</td> <td><input id="Email" name="Email" type="text" /></td> </tr> <tr> <td></td> <td><input type="submit" value="Submit"/></td> </tr> </table> </div> <div> @if(result != ""){ <p>Result: @result</p> } </div> </form> </body> </html>
HTML 標記會以三個文字方塊來建立表單。 在程式碼中,您使用
IsPost
屬性在開始處理前判斷頁面是否已提交。第一個工作是取得使用者輸入,並將它指派給變數。 然後,程式碼會將個別變數的值串連成一個逗號分隔字串,這會儲存在不同的變數中。 請注意,逗號分隔符號是包含在引號 (“,”) 中的字串,因為您實際上是將逗號內嵌到您正在建立的大型字串中。 您在串連在一起的資料結尾新增
Environment.NewLine
。 這會新增分行符號 (新行字元)。 您使用所有這些串連所建立的是一個字串,看起來像這樣:David,Jones,davidj@contoso.com
(結尾有不可見的分行符號。)
然後,您可以建立變數 (
dataFile
),其中包含要在當中儲存資料的檔案位置和名稱。 設定位置需要稍微進行特殊處理。 在網站中,在程式碼中對 Web 伺服器上的檔案參考絕對路徑,例如 C:\Folder\File.txt,是不當的做法。 如果網站已移動,絕對路徑將是錯的。 此外,對於託管的網站 (而不是在您自己的電腦上),您通常連撰寫程式碼時的正確路徑為何都不知道。但有時候 (就像現在一樣,用於寫入檔案),您需要完整的路徑。 解決方法是使用
Server
物件的MapPath
方法。 這會傳回網站的完整路徑。 若要取得網站根目錄的路徑,您使用MapPath
的~
運算子 (代表網站的虛擬根目錄)。 (您也可以將子資料夾名稱傳遞給它,例如 ~/App_Data/,以取得該子資料夾的路徑)。然後,您可以將其他資訊串連至方法傳回的任何內容,以建立完整的路徑。 在此範例中,您會新增檔案名稱。 (您可以在 使用 Razor 語法進行 ASP.NET Web Pages 程式設計簡介深入了解如何使用檔案和資料夾路徑。檔案會儲存在 App_Data 資料夾中。 此資料夾是 ASP.NET 中用來儲存資料檔案的特殊資料夾,如在 ASP.NET Web Pages 網站中使用資料庫簡介中所述。
File
物件的WriteAllText
方法會將資料寫入檔案。 此方法採用兩個參數:要寫入之檔案的名稱 (含路徑),以及要寫入的實際資料。 請注意,第一個參數的名稱有一個@
字元做為前置詞。 這會告知 ASP.NET 您提供的是逐字字串常值,且「/」之類的字元不應該以特殊方式解譯。 (如需詳細資訊,請參閱使用 Razor 語法進行 ASP.NET Web 程式設計簡介。)注意
為了讓程式碼將檔案儲存在 App_Data 資料夾中,應用程式需要該資料夾的讀寫權限。 在您的開發電腦上,這通常不是問題。 然而,當您將網站發佈至主機提供者的 Web 伺服器時,可能需要明確設定這些權限。 如果您在主機提供者的伺服器上執行此程式碼並收到錯誤,請洽詢主機提供者,以了解如何設定這些權限。
在瀏覽器中執行頁面。
在欄位中輸入值,然後按一下 [提交]。
關閉瀏覽器。
返回專案並重新整理檢視。
開啟 data.txt 檔案。 您在表單中提交的資料位於檔案中。
關閉 data.txt 檔案。
將資料附加至現有檔案
在上一個範例中,您使用 WriteAllText
建立的文字檔中只有一個資料片段。 如果您再次呼叫方法並傳遞相同的檔名,則會完全覆寫現有的檔案。 不過,建立檔案之後,您通常會想要將新資料新增至檔案結尾。 您可以使用 File
物件的 AppendAllText
方法來執行此動作。
在網站中,製作 UserData.cshtml 檔案的複本,並將該複本命名為 UserDataMultiple.cshtml。
將開始
<!DOCTYPE html>
標籤前面的程式碼區塊取代為以下程式碼區塊:@{ var result = ""; if (IsPost) { var firstName = Request["FirstName"]; var lastName = Request["LastName"]; var email = Request["Email"]; var userData = firstName + "," + lastName + "," + email + Environment.NewLine; var dataFile = Server.MapPath("~/App_Data/data.txt"); File.AppendAllText (@dataFile, userData); result = "Information saved."; } }
此程式碼有上一個範例中的變更。 它不使用
WriteAllText
,而是使用the AppendAllText
方法。 方法很類似,不同之處在於AppendAllText
將資料新增至檔案結尾。 就跟WriteAllText
一樣,如果該檔案尚不存在,AppendAllText
就會建立它。在瀏覽器中執行頁面。
輸入欄位的值,然後按一下 [提交]。
新增更多資料並再次提交表單。
返回您的專案,以滑鼠右鍵按一下專案資料夾,然後按一下 [重新整理]。
開啟 data.txt 檔案。 它現在包含您剛才輸入的新資料。
從檔案中讀取和顯示資料
即使您不需要將資料寫入文字檔,有時可能需要從其中讀取資料。 若要這麼做,您可以再次使用 File
物件。 您可以使用 File
物件個別讀取每一行 (以分行符號分隔),或讀取個別項目,無論它們如何分隔。
此程序示範如何讀取及顯示您在上一個範例中建立的資料。
在網站的根目錄中,建立一個名為 DisplayData.cshtml 的新檔案。
將現有內容取代如下:
@{ var result = ""; Array userData = null; char[] delimiterChar = {','}; var dataFile = Server.MapPath("~/App_Data/data.txt"); if (File.Exists(dataFile)) { userData = File.ReadAllLines(dataFile); if (userData == null) { // Empty file. result = "The file is empty."; } } else { // File does not exist. result = "The file does not exist."; } } <!DOCTYPE html> <html> <head> <title>Reading Data from a File</title> </head> <body> <div> <h1>Reading Data from a File</h1> @result @if (result == "") { <ol> @foreach (string dataLine in userData) { <li> User <ul> @foreach (string dataItem in dataLine.Split(delimiterChar)) { <li>@dataItem</li > } </ul> </li> } </ol> } </div> </body> </html>
程式碼一開始會使用此方法呼叫,將您在上一個範例中建立的檔案讀入名為
userData
的變數:File.ReadAllLines(dataFile)
執行此動作的程式碼位於
if
陳述式內。 當您想要讀取檔案時,最好先使用File.Exists
方法來判斷檔案是否可用。 程式碼也會檢查檔案是否空白。頁面主體包含兩個
foreach
迴圈,一個巢狀置於另一個迴圈內。 外部foreach
迴圈會一次從資料檔案取得一行。 在本例中,這些行是由檔案中的分行符號所定義,也就是說,每個資料項目都位於自己的行上。 外部迴圈會在已排序的清單 (<ol>
元素) 內建立新項目 (<li>
元素)。內部迴圈會使用逗號做為分隔符號,將每個資料行分割成項目 (欄位)。 (根據上一個範例,這表示每一行都包含三個欄位:名字、姓氏和電子郵件地址,各自以逗號分隔)。內部迴圈也會建立
<ul>
清單,並針對資料行中的每個欄位顯示一個清單項目。此程式碼說明如何使用兩種資料類型:陣列和
char
資料類型。 陣列是必要的,因為File.ReadAllLines
方法會傳回資料做為陣列。char
資料類型是必要的,因為Split
方法會傳回array
,其中每個元素都是類型char
。 (如需有關陣列的資訊,請參閱使用 Razor 語法進行 ASP.NET Web 程式設計簡介。)在瀏覽器中執行頁面。 隨即顯示您為前一個範例輸入的資料。
提示
顯示來自 Microsoft Excel 逗號分隔檔案的資料
您可以使用 Microsoft Excel,將試算表中包含的資料儲存為逗號分隔的檔案 (.csv 檔案)。 當您這麼做時,檔案會以純文字儲存,而不是以 Excel 格式儲存。 試算表中的每一列在文字檔中都會以分行符號分隔,而每個資料項目都會以逗號分隔。 您可以使用上一個範例中顯示的程式碼,藉由在程式碼中變更資料檔名稱案,來讀取 Excel 逗號分隔的檔案。
刪除檔案
若要從您的網站刪除檔案,您可以使用 File.Delete
方法。 此程序說明如果使用者知道檔案的名稱,如何讓他們從 images 資料夾刪除影像 (.jpg 檔案)。
注意
重要事項 在正式環境的網站中,您通常會限制允許誰對資料進行變更。 如需有關如何設定成員資格以及如何授權使用者在網站上執行工作的資訊,請參閱將安全性和成員資格新增至 ASP.NET Web Pages 網站。
在網站中,建立名為 images 的子資料夾。
將一或多個 .jpg 檔案複製到 images 資料夾。
在網站的根目錄中,建立名為 FileDelete.cshtml 的新檔案。
將現有內容取代如下:
@{ bool deleteSuccess = false; var photoName = ""; if (IsPost) { photoName = Request["photoFileName"] + ".jpg"; var fullPath = Server.MapPath("~/images/" + photoName); if (File.Exists(fullPath)) { File.Delete(fullPath); deleteSuccess = true; } } } <!DOCTYPE html> <html> <head> <title>Delete a Photo</title> </head> <body> <h1>Delete a Photo from the Site</h1> <form name="deletePhoto" action="" method="post"> <p>File name of image to delete (without .jpg extension): <input name="photoFileName" type="text" value="" /> </p> <p><input type="submit" value="Submit" /></p> </form> @if(deleteSuccess) { <p> @photoName deleted! </p> } </body> </html>
此頁面包含表單,使用者可以在其中輸入影像檔的名稱。 他們不輸入 .jpg 副檔名;藉由像這樣限制檔案名稱,有助於防止使用者刪除網站上的任意檔案。
程式碼會讀取使用者輸入的檔案名稱,然後建構完整的路徑。 若要建立路徑,程式碼會使用目前的網站路徑 (如
Server.MapPath
方法所傳回)、images 資料夾名稱、使用者提供的名稱,以及「.jpg」作為常值字串。為了刪除檔案,程式碼會呼叫
File.Delete
方法,並傳遞您剛才建構的完整路徑。 在標記結尾,程式碼會顯示確認訊息,指出檔案已刪除。在瀏覽器中執行頁面。
輸入要刪除的檔案名稱,然後按一下 [提交]。 如果已刪除檔案,則會在頁面底部顯示檔案的名稱。
讓使用者上傳檔案
FileUpload
協助程式可讓使用者將檔案上傳至您的網站。 下列程序說明如何讓使用者上傳單一檔案。
如果您之前尚未新增,請依照在 ASP.NET Web Pages 網站中安裝協助程式中所述,將 ASP.NET Web 協助程式庫新增至您的網站。
在 App_Data 資料夾中,建立新的資料夾,並將它命名為 UploadedFiles。
在根目錄中,建立名為 FileUpload.cshtml 的新檔案。
以下列取代頁面中的現有內容:
@using Microsoft.Web.Helpers; @{ var fileName = ""; if (IsPost) { var fileSavePath = ""; var uploadedFile = Request.Files[0]; fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); } } <!DOCTYPE html> <html> <head> <title>FileUpload - Single-File Example</title> </head> <body> <h1>FileUpload - Single-File Example</h1> @FileUpload.GetHtml( initialNumberOfFiles:1, allowMoreFilesToBeAdded:false, includeFormTag:true, uploadText:"Upload") @if (IsPost) { <span>File uploaded!</span><br/> } </body> </html>
頁面的主體部分會使用
FileUpload
協助程式來建立您可能已熟悉的上傳方塊和按鈕:您為
FileUpload
協助程式設定的屬性會指定您想要對要上傳的檔案使用單一方塊,以及您想要提交按鈕顯示上傳字樣。 (您稍後將在文章中新增更多方塊。)當使用者按一下 [上傳] 時,頁面頂端的程式碼會取得檔案並儲存檔案。 您通常用來從表單欄位取得值的
Request
物件也會有一個Files
陣列,其中包含已上傳的檔案 (一或多個檔案)。 您可以從陣列中的特定位置取得個別檔案,例如,若要取得第一個上傳的檔案,您可以取得Request.Files[0]
,要取得第二個檔案,則取得Request.Files[1]
,依此類推。 (請記住,在程式設計中,計數通常從零開始。)當您擷取上傳的檔案時,您會將其放入變數中 (在這裡,為
uploadedFile
),以便您進行操控。 若要判斷已上傳檔案的名稱,只要取得其FileName
屬性即可。 不過,當使用者上傳檔案時,FileName
會包含使用者的原始名稱,其中包含整個路徑。 它看起來如下:C:\Users\Public\Sample.txt
不過,您不會想要所有的路徑資訊,因為這是使用者電腦上的路徑,而不是伺服器的路徑。 您只需要實際的檔案名稱 (Sample.txt)。 您可以使用
Path.GetFileName
方法,從路徑只去除檔案,如下所示:Path.GetFileName(uploadedFile.FileName)
Path
物件是一個公用程式,其中包含一些與此類似的方法,可用來去除路徑、合併路徑等等。取得上傳檔案的名稱之後,您可以針對要儲存上傳檔案的網站位置建立新的路徑。 在本例中,您會結合
Server.MapPath
、資料夾名稱 (App_Data/UploadedFiles),以及新去除的檔案名稱,以建立新的路徑。 然後,您可以呼叫上傳檔案的SaveAs
方法,以實際儲存盤案。在瀏覽器中執行頁面。
按一下 [瀏覽],然後選擇要上傳的檔案。
[瀏覽] 按鈕旁的文字方塊將包含路徑和檔案位置。
按一下 [上傳] 。
在網站中,以滑鼠右鍵按一下專案資料夾,然後按一下 [重新整理]。
開啟 UploadedFiles 資料夾。 您上傳的檔案位於資料夾中。
讓使用者上傳多個檔案
在上一個範例中,您讓使用者上傳一個檔案。 但是您可以使用 FileUpload
協助程式一次上傳多個檔案。 這適用於一次上傳一個檔案很浪費時間的情況,例如上傳相片。 (您可以在在 ASP.NET Web Pages 網站中使用影像中閱讀有關上傳相片的資訊)。此範例說明如何讓使用者一次上傳兩個檔案,不過您可以使用相同的方法來上傳更多檔案。
若尚未完成,請依照在 ASP.NET Web Pages 網站中安裝協助程式中所述,將 ASP.NET Web 協助程式庫新增至您的網站。
建立名為 FileUploadMultiple.cshtml 的新頁面。
以下列取代頁面中的現有內容:
@using Microsoft.Web.Helpers; @{ var message = ""; if (IsPost) { var fileName = ""; var fileSavePath = ""; int numFiles = Request.Files.Count; int uploadedCount = 0; for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); fileSavePath = Server.MapPath("~/App_Data/UploadedFiles/" + fileName); uploadedFile.SaveAs(fileSavePath); uploadedCount++; } } message = "File upload complete. Total files uploaded: " + uploadedCount.ToString(); } } <!DOCTYPE html> <html> <head><title>FileUpload - Multiple File Example</title></head> <body> <form id="myForm" method="post" enctype="multipart/form-data" action=""> <div> <h1>File Upload - Multiple-File Example</h1> @if (!IsPost) { @FileUpload.GetHtml( initialNumberOfFiles:2, allowMoreFilesToBeAdded:true, includeFormTag:true, addText:"Add another file", uploadText:"Upload") } <span>@message</span> </div> </form> </body> </html>
在此範例中,頁面主體中的
FileUpload
協助程式會設定為讓使用者預設上傳兩個檔案。 因為allowMoreFilesToBeAdded
設定為true
,因此協助程式會轉譯連結,讓使用者新增更多上傳方塊:為了處理使用者上傳的檔案,程式碼會使用您在上一個範例中使用的相同基本方法,從
Request.Files
中取得檔案,然後儲存該檔案。 (包括您為了取得正確的檔案名稱和路徑所需執行的各種動作)。這次的差別是使用者可能上傳多個檔案,而且您不知道有多少。 若想知道,您可以取得Request.Files.Count
。有了這個數字,您就可以循環
Request.Files
,轉而擷取每個檔案,然後儲存它。 當您想要對集合循環已知次數時,可以使用for
迴圈,如下所示:for(int i =0; i < numFiles; i++) { var uploadedFile = Request.Files[i]; if (uploadedFile.ContentLength > 0) { fileName = Path.GetFileName(uploadedFile.FileName); // etc. }
變數
i
只是一個臨時計數器,會從零計算到您設定的任何上限。 在本例中,上限是檔案數目。 但是,由於計數器從零開始,如同在 ASP.NET 中一般的計數情況,上限實際上比檔案計數少一個。 (如果上傳三個檔案,則計數為零到 2)。uploadedCount
變數會加總成功上傳和儲存的所有檔案。 此程式碼已考慮預期檔案可能無法上傳的可能性。在瀏覽器中執行頁面。 瀏覽器會顯示頁面及其兩個上傳方塊。
選擇要上傳的兩個檔案。
按一下 [新增其他檔案]。 頁面會顯示新的上傳方塊。
按一下 [上傳] 。
在網站中,以滑鼠右鍵按一下專案資料夾,然後按一下 [重新整理]。
開啟 UploadedFiles 資料夾,以查看已成功上傳的檔案。