TShopping

 找回密碼
 註冊
搜索
查看: 3621|回復: 0
打印 上一主題 下一主題

[教學] PHP 檔案上傳、錯誤判斷

[複製鏈接]
跳轉到指定樓層
1#
發表於 2010-4-28 23:33:05 | 只看該作者 回帖獎勵 |倒序瀏覽 |閱讀模式
 
Push to Facebook
一般上傳檔案的程式流程是如何運作,預設可以使用的變數與限制方式,這些包括如何取得被上傳的檔案名稱、大小、格式、暫存檔名,預設可以用來限制上傳大小的隱藏欄位名稱,以及如何在上傳的過程中除錯等等。

學習重點:

  在這個章節中我們將會學習到幾個與檔案上傳相關的問題,如該怎樣上傳檔案,一般上傳檔案的程式流程是如何運作,預設可以使用的變數與限制方式,這些包括如何取得被上傳的檔案名稱、大小、格式、暫存檔名,預設可以用來限制上傳大小的隱藏欄位名稱,以及如何在上傳的過程中除錯等等。

  這邊我們只會探討到單一的檔案上傳與單一筆記錄的儲存,多筆檔案上傳與多筆記錄儲存會於相簿章節中討論。

  在檔案上傳這個章節中,顧名思義就是介紹如何利用瀏覽器的介面搭配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。


【範例檔案】 – 開啟範例檔案upload.php

 Step1. 開啟頁面後,請在表格中加上一個隱藏欄位、一個檔案欄位、一個按鈕,必須注意的是隱藏欄位必須是表單中的第一個元件。

 Step2. 接著將隱藏欄位命名為MAX_FILE_SIZE、值為1000000,這是預設用來限制上傳檔案大小的欄位,它應該被放在表單中所有元件中的第一個位置,限制的上傳值即為該欄位值,單位為Byte。

  檔案欄位命名為files,最後表單的『動作』,編碼則是multipart/form-data。

  在這裡我們可以看到有五個資訊輸出,包括了檔案名稱、大小、格式、暫存名稱、錯誤代碼,這些都是預設就可以使用的變數與資訊,其中的 files 即為檔案欄位名稱,也就是說若你將檔案欄位名稱命名為ourfile,這裡的各個資訊便需使用$_FILES['ourfile']['xxx']。

其中的:

  ‧$_FILES['files']['name'] 這是使用者上傳的原始檔案名稱。
  ‧$_FILES['files']['size'] 為檔案大小,單位為Byte。
  ‧$_FILES['files']['tmp_name'] 為檔案上傳完畢後於伺服器中暫存的位置。
  ‧$_FILES['files']['type'] 為檔案的MIME格式。
  ‧$_FILES['files']['error'] 檔案上傳的錯誤代碼,在後面我們會針對這個變數的值做處理(PHP 4.2.0以上版本才支援)。
  
  其實我們在index.php所做的幾個簡單步驟便已經做到將檔案上傳的功能,只不過這時候檔案會是位於$_FILES['files']['tmp_name']的位置(伺服器中的暫存位置),其中的MAX_FILE_SIZE隱藏欄位若沒有加上這個欄位也沒有關係,自然有upload_max_filesize等項目來限制上傳的大小,這時候先來試試前面所做的是否都能運作。

[錯誤判斷]
  如果我們可以看到相關的資訊,那麼代表前面的步驟沒有問題,接著下來便針對上傳的錯誤做相關的提示訊息,錯誤訊息前面提過會記錄在$_FILES['files']['error']。

 Step1. 程式碼下加上下列程式。



 
  1. if($_FILES['files']['error'] > 0){
  2.   switch($_FILES['files']['error']){
  3.     case 1 : die("檔案大小超出 php.ini:upload_max_filesize 限制");    
  4.           case 2 : die("檔案大小超出 MAX_FILE_SIZE 限制");
  5.    case 3 : die("檔案僅被部分上傳");
  6.    case 4 : die("檔案未被上傳");
  7.   }
  8.  }
複製代碼


  其中$_FILES['files']['error']若等於0則代表上傳的過程中沒有錯誤,當$_FILES['files']['error']大於0時,程式會依據$_FILES['files']['error']的值輸出相關的提示訊息並終止程式的執行。

  這時候我們可以找一個大於1MB的檔案上傳,可以看到的是只有檔案名稱是正常顯示的,錯誤代碼為2因為上傳的檔案大小超過MAX_FILE_SIZE隱藏欄位的值。

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

 
  1. if(is_uploaded_file($_FILES['files']['tmp_name'])){
  2.   $DestDIR = "files";
  3.   if(!is_dir($DestDIR) || !is_writeable($DestDIR))
  4.    die("目錄不存在或無法寫入");

  5.   $File_Extension = explode(".", $_FILES['files']['name']);
  6.    $File_Extension = $File_Extension[count($File_Extension)-1];
  7.    $ServerFilename =date("YmdHis") . "." . $File_Extension;
  8.   copy($_FILES['files']['tmp_name'] , $DestDIR . "/" . $ServerFilename );
  9.  }
複製代碼


  一般我們先會用is_uploaded_files()來確認檔案是否是真正被上傳與存在於伺服器上(也是為了安全性),因為表單送出之後檔案的位置與名稱會在伺服器的暫存目錄中,因此用is_uploaded_file($_FILES['files']['tmp_name'])來判斷,若是才執行下面的動作,接著的程式主要是定義檔名、判斷目錄、複製檔案三個步驟。

  18列中我們定義了目的的資料夾files,我們可以用is_dir與is_writeable來判斷目錄是否存在與目錄是否可以寫入,19列中兩個函示前面都被加了驚嘆號(!),這會將回傳的TRUE、FALSE給反相,也就是TRUE變為FALSE、FALSE變為TRUE,因此19、20列我們可以看做是『若目錄不存在 或(||) 目錄無法寫入,則輸出目錄不存在或無法寫入,然後終止程式執行』。

 
  1. $File_Extension = explode(".", $_FILES['files']['name']);
複製代碼


  取得檔案副檔名,explode(".", $_FILES['files']['name'])可以看成,將$_FILES['files']['name']的值,以逗點(.)作為分隔,傳回陣列的形式,假設$_FILES['files']['name']等於DSC012345.JPG,那麼以逗號分隔後即為DSC012345與JPG,而這兩個值會被丟到左邊的$File_Extension變數,結果即為$File_Extension[0]=DSC012345、$File_Extension[1]=JPG。

  在執行的結果我們可以看到$File_Extension[1]的值為副檔名,但是有的檔案可能會有好幾個逗點例如DSC.012345.JPG,那麼這個時候副檔名的位置應該就是$File_Extension[2],程式主要在處理這個狀況。

 
  1. $File_Extension = $File_Extension[count($File_Extension)-1];
複製代碼


  我們可以注意到副檔名一定會是在最後的位置,這時候可以利用count()來統計陣列的元素個數,這個值會與副檔名的陣列索引值差1,因此$File_Extension[count($File_Extension)-1]可以用來確保索引(把整個粗體部分看成1個索引)一定在副檔名的位置,最後我們將這個值重新丟回$File_Extension,這時候$File_Extension便不再是陣列而是儲存副檔名了。

 
  1. $ServerFilename =date("YmdHis") . "." . $File_Extension;
複製代碼


  為了避免檔案名稱重複而使伺服器上的檔案被覆蓋,因此這個檔案上傳系統的規劃是,伺服器上的檔名是使用上傳的 年月日時分秒.副檔名 作為檔名,我們定義這個變數叫做$ServerFilename,主檔名的部分使用date()函示產生年月日時分秒,接著連接一個逗點與副檔名變數$File_Extension,在使用者下載檔案的時候我們會用一點技巧使其能夠直接儲存為原始檔名。。

 
  1. copy($_FILES['files']['tmp_name'] , $DestDIR . "/" . $ServerFilename );
複製代碼


  前面我們僅是將檔案上傳至伺服器的暫存目錄中,這時候必須使用copy()函示來將檔案複製到我們所要的目錄中,copy()函示的語法為 copy( 來源路徑檔名 , 目的路徑檔名 ) ,來源的路徑檔名已經在$_FILES['files']['tmp_name']中了,而目的位置則是用 $DestDIR . "/" . $ServerFilename 連接成一個相對路徑。

  講了這麼多後直接使用瀏覽器開啟網頁來真正上傳一次檔案吧,上傳完畢後這次就可以在files目錄下真正看到所上傳的檔案,檔名便為上傳的時間。

Tips

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

 

臉書網友討論
*滑块验证:
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2024-5-8 16:06 , Processed in 0.047574 second(s), 18 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表