【Dreamweaver 8 & PHP 網頁資料庫】:: 試閱章節 14-2-1 建立與讀取表單變數陣列
Chapter 13 檔案上傳系統 範例展示
學習重點:
在這個章節中我們將會學習到幾個與檔案上傳相關的問題,如該怎樣上傳檔案,一般上傳檔案的程式流程是如何運作,預設可以使用的變數與限制方式,這些包括如何取得被上傳的檔案名稱、大小、格式、暫存檔名,預設可以用來限制上傳大小的隱藏欄位名稱,以及如何在上傳的過程中除錯等等。
這邊我們只會探討到單一的檔案上傳與單一筆記錄的儲存,多筆檔案上傳與多筆記錄儲存會於相簿章節中討論。
在檔案上傳這個章節中,顧名思義就是介紹如何利用瀏覽器的介面搭配PHP函示上傳檔案,在這之前於php.ini中有幾點必須注意到的是:
- file_uploads 項目是否設定為On(預設)。
- upload_max_filesize 為上傳檔案的最大限制,預設為2MB(2M)。
如果想要使上傳的檔案大小上限增加時,除了將上述的upload_max_filesize加大以外,另外還需要考慮到:
- max_execution_time 最大執行時間,預設為30秒。
- memory_limit 記憶體限制,預設為8M。
- post_max_size POST的資料量限制,預設為8M。
13-1 準備工作
13-2 檔案上傳
[13-2-1 錯誤判斷]
[13-2-2 複製檔案]
13-3 寫入記錄
13-4 檢視頁面
13-5 刪除檔案與記錄
13-6 下載檔案
13-7 專題延伸
13-2 檔案上傳
首先我們便來看看檔案上傳,PHP中一個典型的檔案上傳流程是:
- 提供上傳檔案
- 判斷錯誤
- 複製暫存檔案至指定目錄下(copy()函示)。
【範例檔案】 — 開啟範例檔案upload.php
Step1. 開啟頁面後,請在表格中加上一個隱藏欄位、一個檔案欄位、一個按鈕,必須注意的是隱藏欄位必須是表單中的第一個元件。

圖13-2-01
Step2. 接著將隱藏欄位命名為MAX_FILE_SIZE、值為1000000,這是預設用來限制上傳檔案大小的欄位,它應該被放在表單中所有元件中的第一個位置,限制的上傳值即為該欄位值,單位為Byte。
檔案欄位命名為myfile,最後表單的『動作』目標設至add.php,編碼則是multipart/form-data。

圖13-2-02

圖13-2-03

圖13-2-04
接著看到的是index.php表單中動作目標的add.php,我們先來瞭解該如何取得上傳檔案的資訊。
【範例檔案】 — 開啟範例檔案add.php
開啟檔案後我們在頁面上方加上如下程式碼。

圖13-2-05
在這裡我們可以看到有五個資訊輸出,包括了檔案名稱、大小、格式、暫存名稱、錯誤代碼,這些都是預設就可以使用的變數與資訊,其中的 myfile 即為index.php中的檔案欄位名稱,也就是說若你將檔案欄位名稱命名為ourfile,這裡的各個資訊便需使用$_FILES[‘ourfile’][‘xxx’]。
其中的:
- $_FILES[‘myfile’][‘name’] 這是使用者上傳的原始檔案名稱。
- $_FILES[‘myfile’][‘size’] 為檔案大小,單位為Byte。
- $_FILES[‘myfile’][‘tmp_name’] 為檔案上傳完畢後於伺服器中暫存的位置。
- $_FILES[‘myfile’][‘type’] 為檔案的MIME格式。
- $_FILES[‘myfile’][‘error’] 檔案上傳的錯誤代碼,在後面我們會針對這個變數的值做處理(PHP 4.2.0以上版本才支援)。
其實我們在index.php所做的幾個簡單步驟便已經做到將檔案上傳的功能,只不過這時候檔案會是位於$_FILES[‘myfile’][‘tmp_name’]的位置(伺服器中的暫存位置),其中的MAX_FILE_SIZE隱藏欄位若沒有加上這個欄位也沒有關係,自然有upload_max_filesize等項目來限制上傳的大小,這時候先來試試前面所做的是否都能運作。

圖13-2-06
選擇一個小於1MB的檔案上傳
↓

圖13-2-07
顯示該上傳檔案的相關資訊
[錯誤判斷]
如果我們在add.php中可以看到相關的資訊,那麼代表前面的步驟沒有問題,接著下來便針對上傳的錯誤做相關的提示訊息,錯誤訊息前面提過會記錄在$_FILES[‘myfile’][‘error’]。
Step1. 同樣是在add.php中,我們在剛剛的程式碼下加上下列程式。

圖13-2-08
|
08 if($_FILES[‘myfile’][‘error’] > 0){ |
其中$_FILES[‘myfile’][‘error’]若等於0則代表上傳的過程中沒有錯誤,當$_FILES[‘myfile’][‘error’]大於0時,程式會依據$_FILES[‘myfile’][‘error’]的值輸出相關的提示訊息並終止程式的執行。
這時候我們可以找一個大於1MB的檔案上傳,可以看到的是只有檔案名稱是正常顯示的,錯誤代碼為2因為上傳的檔案大小超過index.php中MAX_FILE_SIZE隱藏欄位的值。

圖13-2-09
[複製檔案]
在瞭解MAX_FILE_SIZE隱藏欄位與如何利用$_FILES[‘myfile’][‘error’]所提供的資訊來除錯後,接著要做的便是將檔案由伺服器的暫存位置複製至我們所需要的位置,在前面的程式碼下方輸入下列程式。

圖13-2-10
|
17 if(is_uploaded_file($_FILES[‘myfile’][‘tmp_name’])){ |
一般我們先會用is_uploaded_files()來確認檔案是否是真正被上傳與存在於伺服器上(也是為了安全性),因為表單送出之後檔案的位置與名稱會在伺服器的暫存目錄中,因此用is_uploaded_file($_FILES[‘myfile’][‘tmp_name’])來判斷,若是才執行下面的動作,接著的程式主要是定義檔名、判斷目錄、複製檔案三個步驟。
18列中我們定義了目的的資料夾files,我們可以用is_dir與is_writeable來判斷目錄是否存在與目錄是否可以寫入,19列中兩個函示前面都被加了驚嘆號(!),這會將回傳的TRUE、FALSE給反相,也就是TRUE變為FALSE、FALSE變為TRUE,因此19、20列我們可以看做是『若目錄不存在 或(||) 目錄無法寫入,則輸出目錄不存在或無法寫入,然後終止程式執行』。
|
22 $File_Extension = explode(".", $_FILES[‘myfile’][‘name’]); |
22與23列都在處理取得檔案副檔名,22列中的explode(".", $_FILES[‘myfile’][‘name’])可以看成,將$_FILES[‘myfile’][‘name’]的值,以逗點(.)作為分隔,傳回陣列的形式,假設$_FILES[‘myfile’][‘name’]等於DSC012345.JPG,那麼以逗號分隔後即為DSC012345與JPG,而這兩個值會被丟到左邊的$File_Extension變數,結果即為$File_Extension[0]=DSC012345、$File_Extension[1]=JPG。
在22列執行的結果我們可以看到$File_Extension[1]的值為副檔名,但是有的檔案可能會有好幾個逗點例如DSC.012345.JPG,那麼這個時候副檔名的位置應該就是$File_Extension[2],23列的程式主要在處理這個狀況。
|
23 $File_Extension = $File_Extension[count($File_Extension)-1]; |
我們可以注意到副檔名一定會是在最後的位置,這時候可以利用count()來統計陣列的元素個數,這個值會與副檔名的陣列索引值差1,因此$File_Extension[count($File_Extension)-1]可以用來確保索引(把整個粗體部分看成1個索引)一定在副檔名的位置,最後我們將這個值重新丟回$File_Extension,這時候$File_Extension便不再是陣列而是儲存副檔名了。
|
24 $ServerFilename =date("YmdHis") . "." . $File_Extension; |
為了避免檔案名稱重複而使伺服器上的檔案被覆蓋,因此這個檔案上傳系統的規劃是,伺服器上的檔名是使用上傳的 年月日時分秒.副檔名 作為檔名,我們在24列定義這個變數叫做$ServerFilename,主檔名的部分使用date()函示產生年月日時分秒,接著連接一個逗點與副檔名變數$File_Extension,在使用者下載檔案的時候我們會用一點技巧使其能夠直接儲存為原始檔名。。
|
25 copy($_FILES[‘myfile’][‘tmp_name’] , $DestDIR . "/" . $ServerFilename ); |
前面我們僅是將檔案上傳至伺服器的暫存目錄中,這時候必須使用copy()函示來將檔案複製到我們所要的目錄中,copy()函示的語法為 copy( 來源路徑檔名 , 目的路徑檔名 ) ,來源的路徑檔名已經在$_FILES[‘myfile’][‘tmp_name’]中了,而目的位置則是用 $DestDIR . "/" . $ServerFilename 連接成一個相對路徑。
講了這麼多後直接使用瀏覽器開啟網頁來真正上傳一次檔案吧,上傳完畢後這次就可以在files目錄下真正看到所上傳的檔案,檔名便為上傳的時間。

圖13-2-11
|
Tips files目錄於Windows系統中必須【沒有】唯讀屬性,若於Unix-Like系統中則必須有寫入權限,一般會設為667。 |

大大,你這個網站太棒了,有教學,還會幫人解答,真是功德無量。這個社會正需要你這種熱血好漢。給你鼓掌敬禮。
希望以後有機會可以像你請教~
請問 我找不到站存檔案在哪
我找不到 丟出去的檔案夾 在哪 😥
你是指圖13-2-07?
熊熊 找到了
原來 錯在 大小寫一定要依樣
狠嚴格的喔~!!!!:grin:
加油~~站長 ! 這個網站不錯!! 多多努力 !!
:neutral:請問這是什麼意思?
該怎麼辦呢= =?
Warning: copy(files/20060411154748.JPG) [function.copy]: failed to open stream: Permission denied in C:\Documents and Settings\new pc\My Documents\My Webs\add.php on line 24
Permission denied
files資料夾在嗎?
不好意思請老師們幫幫我,我找不到解決的辦法,頭髮快掉光了….
我加入以下這段之後
if($_FILES[‘myfile’][‘error’] > 0){
switch($_FILES[‘myfile’][‘error’]){
case 1 : die(“檔案大小超出 php.ini:upload_max_filesize 限制\”);
case 2 : die(“檔案大小超出 MAX_FILE_SIZE 限制\”);
case 3 : die(“檔案僅被部分上傳\”);
case 4 : die(“檔案未被上傳\”);
}
出線錯誤訊息
Parse error: parse error, unexpected ‘{‘ in C:\www\buy\add.php on line 13
{}沒成雙成對…
我的mysql是用xampp架在linux上面想使用dreamweaver連到我遠端的linux server上面但一直出現權限不夠的訊息,我在mysql上的權限都有開請問要如何解決謝謝
Mysql使用者權限有一個 ‘主機’ 的項目新增一個設置為 % 的使用者
謝謝我在試試看若不行我在請教你老師謝謝
:mrgreen::cry::roll:
請問一下,檔案欄位產生後
Enter file name:
預設的[瀏覽]中文字怎麼改成英文呢?
謝謝!
用英文版的他就是英文了…不能改
謝謝您的回答,我照上面的教學和書中的教學,做好後,在上傳檔案資料時,會出現錯誤:
Filename: HCM1.jpg
Size: 185914
Type: image/pjpeg
Temporary Name: C:\WINNT\TEMP\php316.tmp
Error:0
Error: failed to upload file
Temporary Name:並非我原先的設定,書中有提到,若無寫入權限,會自動變為系統預設的TMO資料夾,但是我權限已經開啟,安全性中的IUSR和IWAN這兩個使用者權限我都已經設定為完全控制(OS為WINDOWS 2000),但是還是無法寫入,請問這是什麼問題呢?
C:\WINNT\TEMP\php316.tmp
檔案看起來是已經傳上去了
那怎樣去張制upload file的格式
在這裡就直接判斷副檔名吧
您好,我也有買這本書,但實務上很多php檔案都會上傳到linux主機上,主機上的權限平常會設成701以拒絕存取資料夾,但這樣會順便也拒絕了上傳,用這支程式在windows主機上可以上傳,但在linux主機會被deny,如何在這個程式的某個地方增加上傳時變更資料夾為可寫?
例如這是我測試的:
<?php
//chmod (“../”, 777); // decimal; probably incorrect
//chmod (“../photos”, 0777); // decimal; probably incorrect
//chmod (“../photos/thum”, 0777); // decimal; probably incorrect
//chmod (“/”, “u+rwx,go+rx”); // string; incorrect
//chmod (“/”, 0777); // octal; correct value of mode
?>
不妨自行在FTP建立、修改權限
我的環境是php5.3.1+IIS FastCGI
我的問題是”輸出的目的資料夾”雖存在但無法寫入,導致無法執行copy指令
想請教您要如何解決?謝謝!
我把php5.3.1移除改裝php5.2.0+IIS CGI
結果這回輸出目的資料匣可寫入,但是copy()依然無法執行,訊息如下:
PHP Warning: copy(./img/annie.gif) [function.copy]: failed to open stream
請幫幫忙!
IIS權限問題吧
試著用他去管理資料夾的權限
😯
完全照著您的步驟做
可是這行會出現錯誤→ switch($_FILES[‘myfile’][‘error’]){
把那整段註解掉之後會換這行錯→ $DestDIR = “files”;
請幫幫我=( 看不出問題到底出在哪…謝謝
HI =P
我把字重新打過就OK了 謝謝分享^^
請問大大~~
如果我想把日期檔名改成檔案原來的名字
該怎麼修改呢??
因為我怎麼修改都是錯誤的
•$_FILES[‘myfile’][‘name’] 就是原始檔名囉
請問
如果這個程式我想多檔上傳
該怎麼去寫呢???
你可以參考CS3版本的書或CS5
請問Cttlee我依照您的書以上步驟製作,點選我要的檔案接著送出,但是我的畫面會顯示檔案名稱 大小 格式 暫存名稱 錯誤代碼等名稱,不過後面的DSCF1668.JPG 113349…..等等,都不會顯示,請問是哪裡出錯了?謝謝
我也有這疑問…
請問如果要做表單 附加檔案 寄出後 在我的信箱也要收到上傳的檔案
要如何寫
謝謝