首頁 >web前端 >js教程 >php的檔案上傳入門教學(實例講解)_基礎知識

php的檔案上傳入門教學(實例講解)_基礎知識

WBOY
WBOY原創
2016-05-16 16:52:531885瀏覽

一、文件上传

为了让客户端的用户能够上传文件,我们必须在用户界面中提供一个表单用于提交上传文件的请求。由于上传的文件是一种特殊数据,不同于其它的post数据,所以我们必须给表单设置一个特殊的编码:

复制代码 代码如下:


以上的enctype属性,你可能不太熟悉,因为这常常会被忽略掉。但是,如果http post请求中既有常规数据,又包含文件类数据的话,这个属性就应该显示加上,这样可以提高针对各种浏览器的兼容性。

接下来,我们得向表单中添加一个用于上传文件的字段:

复制代码 代码如下:


上述文件字段在各种浏览器中可能表现会有所不同。对于大多数的浏览器,上述字段都会被渲染成一个文本框加上一个浏览按钮。这样,用户既可以自行输入文件的路径到文本框中,也可以通过浏览按钮从本地硬盘上选择所要上传的文件。但是,在苹果的Safari中,貌似只能使用浏览这种方式。当然,你也可以自定义这个上传框的样式,使它看起来比默认的样式优雅些。

下面,为了更好的阐述怎么样处理文件上传,举一个完整的例子。比如,以下一个表单允许用户向我的本地服务器上上传附件:

复制代码 代码如下:

请上传你的附件:






提示:可以通过php.ini中的upload_max_filesize来设置允许上传文件的最大值。另外,还有一个post_max_size也可以用来设置允许上传的最大表单数据,具体意思就是表单中各种数据之和,所以你也可以通过设置这个字段来控制上传文件的最大值。但是,注意后者的值必须大于前者,因为前者属于后者的一部分表单数据。

php的檔案上傳入門教學(實例講解)_基礎知識
 

圖1. 顯示在firefox中的上傳表單

當這個表單提交的時候,http請求就會被送到upload.php。為了顯示具體哪些資訊可以在upload.php中使用,我在upload.php將其列印出來:

複製程式碼 程式碼如下:

header('Content-Type: text/plain');
print_r($_FILES);


下面來做個試驗,假如我透過以上表單上傳一個本部落格的logo到我的本機伺服器www.360weboy.me/upload.php,看看在upload.php中會輸出什麼資訊:
複製碼 程式碼如下:
Array
        (
          (
           (
                    [name] => boy.jpg
                    [type] => image/jpeg
                    [tmp_name] => D:xampptmpphp1168.tmp
                    [error] => 0
                    [size] => 11490
                )

        )


以上就是檔案上傳後,在全域陣列中的所有關於目前上傳檔案的資訊。但是,我們是否能夠保證這些資訊是安全的,假如name或其它資訊被竄改過了呢?我們時時刻刻需要對來自客戶端的訊息保持警惕!

具體的http請求的各個部分
為了更好的理解文件上傳,我們必須核對下客戶端發送的http請求中到底包含了那些具體的信息。先前我上傳的附件是本部落格的logo,因為是圖片,不太適合我們做以上實驗。所以,我重新上傳一個test.text文字文件,其中具體包含了以下內容:

複製程式碼 程式碼如下:

    360w
    360days
    Life Of A Web Boy

Okay。現在我上傳這個文字文件,在upload.php中會輸出:
複製程式碼 程式碼如下:


        Array
        (
          
                    [name] => test.txt
                       [ tmp_name] => D:xampptmpphp51C0.tmp
                    [且   40
                )

         下相關的瀏覽器發送的http post請求(一些可選的頭部我省略了):



複製程式碼

程式碼如下:


        POST /upload.php HTTP/1.1
        Host: www.360weboy.me        Content-Length: 234

        -----🎜>
        -----🎜>
        -----🎜>
      ------------------------24464570528145
        Content-Disposition: form-data; name="attachment"; filename="test.txt"
        Content-Type: text/plain

        360weboy
        ------------- ----------------24464570528145--

   
從上面的請求格式中有幾個字段我們要關注下的,分別是name, filename以及Content-Type.它們分別表示上傳檔案框在form表單中的欄位名稱-attachment,使用者從本機硬碟上傳的檔案名稱– test.txt,以及上傳的檔案格式– text/plain(代表文字檔案)。然後,我們看到一行空行下面的,就是這個上傳檔案中的具體內容。

二、安全性的加強為了加強檔案上傳中的安全性,我們需要檢查下$_FILES全域數組中的tmp_name和size。為了確保tmp_name指向的文件確實是剛剛使用者在客戶端上傳的文件,而不是指向的類似/etc/passwd,可以使用php中的函數is_uploaded_file()來進行下判斷:



複製程式碼 代碼如下:
       >
        if (is_uploaded_file($filename)) {
             情況下,用戶上傳文件後,可能會將上傳成功的檔案的內容顯示給使用者看下,那麼上述程式碼的檢查尤其重要。

另外一個要檢查的就是上傳檔案的mime-type, 也就是上述upload.php中輸出陣列的type欄位。 我在第一個例子中上傳的是一個圖片,所以$_FILES['attachment']['type']的值為'image/jpeg'。 如果打算在伺服器端只接受image/png, image/jpeg, image/gif, image/x-png 以及image/p-jpeg這些mime-type的圖片,可以用類似下面的程式碼了進行檢查(只是舉個例子,具體程式碼,例如報錯等,應該遵循你的系統中的機制):



複製程式碼


程式碼如下:

     if(!in_array($image['type'], $ allow_mimes)) {
            die('對不起, 你上傳的檔案格式不準確;我們只接受圖片檔案.');
     
   
如你所看到的,我們已經保準了檔案的mime-type是符合伺服器端的要求的。但是,這樣是不是就可以防止惡意使用者上傳其它有害文件,還是不夠的,因為這個mime-type惡意使用者是可以偽裝的。 例如使用者做了一張jpg圖片,在圖片的元資料中寫入了一些惡意的php程式碼,然後儲存為後綴名為php的檔案。當這個惡意檔案上傳的時候,將順利通過伺服器端對於mime-type的檢查,被認為是一張圖片,裡面的危險的php程式碼將會被執行。具體的圖片的元資料類似如下:
複製程式碼 程式碼如下:

程式碼如下:





        File size    : 182007 bytes
          Resolution   : 1197 x 478
        Comment      : passthru($_POST['cmd ']); __halt_compiler();複製程式碼


程式碼如下:



        $allow_mimes = array(
            'image/png' => '.png',            'image/ gif' => '.gif',
            'image/jpeg' => '.jpg',
        🎜>
        $ image = $_FILES['attachment'];

        if(!array_key_exists($image['type'], $allow_mimes )) {
你上傳準確的文件不證;我們只接受圖片檔案.');
        }

        // 取得略去後綴名的檔案名稱:
 $image['name'], '.'));

       // 上字尾名
        $filename .= $allow_mimes[$image['type'];
   
透過上述的程式碼,我們確保即使上傳的圖片的元檔案包含了php程式碼的話,圖片檔案會被重命名為後綴為圖片格式的文件,所以其中的php程式碼也不會被執行了。上述程式碼對正常的上傳的圖片也不會有任何負面影響。
進行了上述的幾步提高安全性的檢查步驟後,如果你只是要把上傳的檔案保存到一個指定的目錄中,那麼就可以使用php的預設函數move_uploaded_file來實現了:


複製碼複製碼

代碼如下:



  '];
        $filename = '/path/to/attachment.txt';

          _filename 保存在暫存目錄中的上傳檔案, 然後成功將其儲存到對應目錄下的attachment.txt檔案中. */
        }
  

你也許還要對上傳檔案的大小進行限制,那麼你可以透過filesize函數來取得上傳檔案的大小,進行判斷後做進一步處理,這具體就不在這將了,自己去折騰吧。

好了,關於文件上傳暫時就寫到這裡吧。希望這篇入門文章對你有幫助。
陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn