PHP上傳檔案設計分析

鴨脖發表於2015-06-13

應用情景:手機APP的上傳圖片的功能,使用HTTP multipart/form-data 協議進行上傳。

基礎知識:

PHP中最重要的一個全域性變數之一,$_FILES,在伺服器端,記錄了multipart/form-data 協議中的檔案資訊。multipart/form-data 協議其實和Post沒啥大的區別,只不過它攜帶的引數的資料格式比較特殊,其中包含了檔案的位元組內容。檔案通過HTTP傳輸到伺服器之後,伺服器作為一個HTTP伺服器,會把這個檔案的位元組內容,暫存在PHP的臨時資料夾裡面,這個資料夾是PHP安裝資料夾中的一個tmp命名的資料夾。需要注意的是,這只是暫存,預設的暫存時間,就是噹噹前的PHP指令碼結束執行之後,這個臨時檔案便會消失,所以需要你在它消失之前,對其進行儲存或者移動。

基本的過程是:

1、獲取$_FILES中的檔案資訊,包括名稱,暫存路徑等,其中重要的資訊有以下五個:

  • $_FILES["file"]["name"] - 被上傳檔案的名稱
  • $_FILES["file"]["type"] - 被上傳檔案的型別
  • $_FILES["file"]["size"] - 被上傳檔案的大小,以位元組計
  • $_FILES["file"]["tmp_name"] - 儲存在伺服器的檔案的臨時副本的名稱
  • $_FILES["file"]["error"] - 由檔案上傳導致的錯誤程式碼

2、檔案大小的限制判斷,因為你不能任由使用者上傳任意大小的檔案,因為很有可能你的伺服器就一直在為這個連線服務,一直在為他傳輸檔案,者不可行。儘管HTTP對報文長度大小沒有做出任何限制,但是你的伺服器程式,比如Apache,Nginx會對使用者上傳的檔案大小做出限制,比如Apache預設應該是8M,這個大小你可以在相應的配置檔案中進行修改。然而,你也可以在程式中進行檢查,比如你希望使用者上傳的圖片大小不超過3M,而上傳的文字大小不超過1M,那麼你就可以通過type和size這兩個引數,進行判斷,如果超過了規定的最大長度,就不做處理,直接返回錯誤程式碼。

3、儲存檔案或者移出暫存資料夾,php中有一個函式move_uploaded_file(name, path)可以移動上傳檔案至指定的path路徑下。但是,目前大部分創業企業,都是用雲伺服器,而如果你使用雲伺服器自身帶的資料盤,沒有使用提供商提供的儲存服務好處多,所以大部分都會使用提供商提供的服務來儲存資料,所以這個函式在這種情況下就失去了作用。我的解決方案在下面會提到。

<?php
if ((($_FILES["file"]["type"] == "image/gif")
|| ($_FILES["file"]["type"] == "image/jpeg")
|| ($_FILES["file"]["type"] == "image/pjpeg"))
&& ($_FILES["file"]["size"] < 20000))
  {
  if ($_FILES["file"]["error"] > 0)
    {
    echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
    }
  else
    {
    echo "Upload: " . $_FILES["file"]["name"] . "<br />";
    echo "Type: " . $_FILES["file"]["type"] . "<br />";
    echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
    echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

    if (file_exists("upload/" . $_FILES["file"]["name"]))
      {
      echo $_FILES["file"]["name"] . " already exists. ";
      }
    else
      {
      move_uploaded_file($_FILES["file"]["tmp_name"],
      "upload/" . $_FILES["file"]["name"]);
      echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
      }
    }
  }
else
  {
  echo "Invalid file";
  }
?>

4.說一下我的解決方案吧,主要步驟如下:

1、判斷型別是否符合要求和大小是否超出規定的最大檔案長度

2、讀取暫存檔案內容,並且載入至Memcache或者Redis中進行快取

3、返回圖片的指紋,或者快取中圖片內容所對應的key,供下面的程式使用,快取有暫存時間,如果不盡快使用圖片內容會被銷燬

4、使用者在使用圖片的時候,會首先將快取中的圖片儲存至指定的雲端儲存盤中(這裡可以加一個適配層,適應不同的儲存服務),然後生成縮略語,儲存縮圖,儲存檔案資訊

基本上就是以上幾個要點

相關文章