PHP入門學習筆記六

一、表單的參數傳遞

1.1 複選框參數傳遞

複選框參數傳遞存在問題,例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (isset($_POST['button'])) {
        echo $_POST['languages'];
    }
?>
    <form action="" method="post">
        語言:<input type="checkbox" name="languages" value="PHP">PHP
        <input type="checkbox" name="languages" value="javascript">javascript
        <input type="checkbox" name="languages" value="node">node
        <input type="checkbox" name="languages" value="vue">vue
        <button type="submit" name="button">確定</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
可以很直觀的發現,複選框當我們選擇兩個以上時只會選擇最後一個,那麼我們需要在複選框的name屬性後加個[ ]表示這個是一系列的數組,如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (isset($_POST['button'])) {
        print_r($_POST['languages']);
    }
?>
    <form action="" method="post">
        語言:<input type="checkbox" name="languages[]" value="PHP">PHP
        <input type="checkbox" name="languages[]" value="javascript">javascript
        <input type="checkbox" name="languages[]" value="node">node
        <input type="checkbox" name="languages[]" value="vue">vue
        <button type="submit" name="button">確定</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
這樣就可以解決複選框的問題了。

1.2 其他表單參數傳遞

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (isset($_POST['button'])) {
        echo '姓名:'.$_POST['username'].'<br/>';
        echo '密碼:'.$_POST['password'].'<br/>';
        echo '性別:'.$_POST['sex'].'<br/>';
        echo '居住地:'.$_POST['area'].'<br/>';
        echo '留言:'.$_POST['mark'].'<br/>';
    }
    echo '<hr/>';
?>
    <form action="" method="post">
        姓名:<input type="text" name="username"><br/>
        密碼:<input type="password" name="password"><br/>
        性別:<input type="radio" name="sex" value="1" checked><input type="radio" name="sex" value="0"><br/>
        愛好:
        居住地:
        <select name="area">
            <option value="amoy">廈門</option>
            <option value="fuzhou">福州</option>
        </select><br/>
        備註:<textarea name="mark" cols="30" rows="5"></textarea>
        <button type="submit" name="button">確定</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述

二、文件參數的傳遞(二進制)

2.1 文件域

開發中需要上傳圖片、音樂、視頻等等,這種上傳傳遞是二進制數據。
文件域:<input type="file" name="image">

2.2 表單enctyoe屬性

enctype 屬性規定在發送到服務器之前應該如何對錶單數據進行編碼。默認地,表單數據會編碼爲 “application/x-www-form-urlencoded”。就是說,在發送到服務器之前,所有字符都會進行編碼。

表單的enctype屬性,默認情況下,表單傳遞的是字符流,不能傳遞二進制,通過enctype屬性設置可以傳遞複合數據。
enctype有三種格式:
在這裏插入圖片描述

  1. application/x-www-form-urlencoded 只能傳字符串,帶格式的,xml
  2. multipart/form-data 能傳字符串或者二進制數據,文件上傳必須設置這個。
  3. text/plain 傳字符串,不帶格式。

2.3 接收文件$_FILES

超全局變量$_FILES是一個二維數組,用來保存客戶端上傳到服務器的文件信息。二維數組的行是文件域的名稱,列有5個。
例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (!empty($_POST)) {
        echo '<pre/>';
        print_r($_FILES);
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="image">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述

  1. name:上傳的文件名
  2. type:上傳的類型,這個類型是MIME類型
  3. size:文件的大小,以字節爲單位
  4. tmp_name:文件上傳時的臨時文件
  5. error:錯誤的編碼(值有0、1、2、3、4、6、7)0表示正確
    error值描述:
error值 錯誤描述
0 正確
1 文件大小超過了php.ini允許的最大值
2 文件大小超過了表單允許的最大值
3 只有部分文件上傳
4 沒有文件上傳
6 找不到臨時文件
7 文件寫入失效

可以在php.ini中設置允許的最大值:
在這裏插入圖片描述
php.ini中設置允許最大爲2M。

設置表單允許的最大值:
在這裏插入圖片描述
只要掌握錯誤號,0和4即可。

2.4 將上傳文件移到指定位置。move_uploaded_file(臨時地址, 目標地址)

函數:move_uploaded_file(臨時地址, 目標地址)
例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (!empty($_POST)) {
        // 如果有文件上傳並且正確,進行上傳文件移到指定位置
        if ($_FILES['image']['error'] == 0) {
            move_uploaded_file($_FILES['image']['tmp_name'], './'.$_FILES['image']['name']);
        }
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="image">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
可以看到已經從桌面上傳到www文件夾下了。

php.ini中與上傳文件相關的一些配置:

  1. post_max_size = 8M(表單允許的最大值)
    在這裏插入圖片描述
  2. upload_max_filesize = 2M(允許上傳文件的大小)
    在這裏插入圖片描述
  3. upload_tmp_dir =“F:/Program/tmp”(指定臨時文件地址)
    在這裏插入圖片描述
  4. file_uploads = On(是否允許文件上傳)
    在這裏插入圖片描述
  5. max_file_uploads = 20(允許同時上傳20個文件)
    在這裏插入圖片描述

2.5 優化文件上傳,同名處理。

在文件上傳時,如果是相同名字的將覆蓋,那這個肯定不是我們想要的,接下來來優化下這個問題。

在這之前,先介紹兩個處理字符串的函數strchr( )strrchr( )。例:

<?php
    $path='counter.name.jpg';
    echo strchr($path, '.');
?>

效果:
在這裏插入圖片描述
strchr( 匹配的字符串,以什麼爲選擇起始標誌) :這個方法從左邊開始匹配。

<?php
    $path='counter.name.jpg';
    echo strrchr($path, '.');
?>

效果:
在這裏插入圖片描述
strrchr( 匹配的字符串,以什麼爲選擇起始標誌) :這個方法從右邊開始匹配。

  1. 通過時間戳拼接3位隨機數做文件名
<?php
    $path='counter.name.jpg';
    echo time().rand(100,999).strrchr($path, '.');
?>

效果:
在這裏插入圖片描述
2. 通過php自帶的uniqid( )做文件名
uniqid(前綴,true)。
例:

<?php
    $path='counter.name.jpg';
    echo uniqid('goods_').strrchr($path, '.'), '<br/>';
    echo uniqid('goods_', true).strrchr($path, '.');
?>

效果:
在這裏插入圖片描述

2.6 驗證文件格式

  1. 判斷文件後綴名。
    例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (!empty($_POST)) {
        $arr=array('.jpg','.png','.gif'); // 允許的擴展名
        $ext=strrchr($_FILES['languages']['name'],'.'); // 上傳文件擴展名
        if (in_array($ext, $arr)) {
            echo '允許上傳';
        }
        else {
            echo '不允許上傳';
        }
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="languages">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
但是如果我在桌面新建一個記事本,aa.txt,然後我將後綴改爲.jpg,那麼它也是允許上傳的,但是他的本質還是文本,所以這裏的安全係數不高。不能防止文件僞裝。

  1. 判斷mime類型
    例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (!empty($_POST)) {
        $arr=array('image/jpeg','image/png','image/gif'); // 允許的擴展名
        $mime=$_FILES['languages']['type']; // mime類型
        if (in_array($mime, $arr)) {
            echo '允許上傳';
        }
        else {
            echo '不允許上傳';
        }
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="languages">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
可以看到判斷mime類型也不能防止文件僞裝。

  1. php_fileinfo擴展
    在php.ini配置中找到如圖:
    在這裏插入圖片描述
    開啓擴展後,就可以調用裏面定義的函數。例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    if (!empty($_POST)) {
        // 1.創建finfo資源
        $info=finfo_open(FILEINFO_MIME_TYPE);
        var_dump($info);
        // 2.將finfo資源和文件做比較
        echo finfo_file($info,$_FILES['languages']['tmp_name']);
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="languages">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
那麼這個就可以防止文件僞裝了,它可以強大到你的記事本是空的都知道,如果寫了內容或者腳本也能分析出來,這邊就不試了,就是在aa.jpg中寫入js腳本,它也能檢測出來。感興趣的小夥伴可以自己試試。

三、優化文件上傳例題

  1. 驗證是否有誤
  2. 驗證格式
  3. 驗證大小
  4. 驗證是否是http上傳
  5. 上傳實現

例:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
<?php
    
    function checkErr($file) {
        $error = $file['error'];
        // 1.驗證錯誤
        if ($error != 0) {
            switch ($error) {
                case 1:
                    return '文件大小超過了php.ini允許的最大值'.ini_get('upload_max_filesize');
                case 2:
                    return '文件大小超過了表單允許的最大值';
                case 3:
                    return '只有部分文件上傳';
                case 4:
                    return '沒有文件上傳';
                case 6:
                    return '找不到臨時文件';
                case 7:
                    return '文件寫入失效';
                default:
                    return '未知錯誤';
            }
        }
        // 2.驗證格式
        $info=finfo_open(FILEINFO_MIME_TYPE);
        $mime=finfo_file($info,$file['tmp_name']);
        $arr=array('image/jpeg','image/png','image/gif');
        if (!in_array($mime,$arr)) {
            return '只能上傳'.implode(',',$arr);
        }
        // 3.驗證大小
        $size=1024000;
        if ($file['size']>$size) {
            return '文件大小不能超過'.number_format($size/1024,1).'kb';
        }
        // 4.驗證是否是http上傳
        if (!is_uploaded_file($file['tmp_name'])) {
            return '文件不是HTTP POST 上傳的<br/>';
        }
        return null;
    }
    if (!empty($_POST)) {
        if ($err = checkErr($_FILES['languages'])) {
            echo $err;
        }
        else {
            // 5.文件上傳
            //$folder=date('Y-m-d H:i:s') // 將當前的時間轉成 年-月-日 小時:分鐘:秒數
            echo $folder=date('Y-m-d'); // 文件夾名稱
            $path="./uploads/${folder}"; // 文件夾路徑
            if (!is_dir($path)) {
                mkdir($path);
            }
            else {
                $filename=uniqid('',true).strrchr($_FILES['languages']['name'], '.'); // 文件名
                $filepath="$path/$filename"; // 文件路徑
                if (move_uploaded_file($_FILES['languages']['tmp_name'], $filepath)) {
                    echo "上傳成功,路徑是:${filepath}";
                }
                else {
                    echo '失敗<br/>';
                }
            }
            
        }
    }
?>
    <form action="" method="post" enctype="multipart/form-data">
        <input type="file" name="languages">
        <button type="submit" name="button">上傳</button>
    </form>
</body>
</html>

效果:
在這裏插入圖片描述
在這裏插入圖片描述
可以看到按照預期的上傳成功了。

在學習的php的路上,如果你覺得本文對你有所幫助的話,那就請關注點贊評論三連吧,謝謝,你的肯定是我寫博的另一個支持。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章