国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

PHP開發(fā)基礎教程之文件上傳

一、PHP文件上傳

在我們?nèi)粘J褂弥薪?jīng)常會遇到很多種這樣的情況:

  • QQ空間里面上傳圖片呀

  • 微信朋友圈上傳圖片

  • 發(fā)郵件里面上傳郵件資料附件

  • 認證的時候要求上傳照片或身份證

  • ?還有各種產(chǎn)品汪(gou)們提出的需求來分析,上傳不同的東西。

  • 而產(chǎn)品汪提出來的需求我們需要實現(xiàn)。

  • 實現(xiàn)文件上傳,是一個PHP程序員必備的技能之一。

通過學習文件上傳,你將透過使用的現(xiàn)象看到文件上傳的本質(zhì)!


二、文件上傳需要注意php.ini文件

在正式講解本章上傳前,我們第一件事情是要注意觀察php.ini文件。

我們第一次開始接觸到如何修改php.ini文件,如果你的配置項與我們說的不一致,請注意修改。

我們來了解每一個配置項。

我們看一下如何修改php.ini。

打開phpstudy中的php.ini配置文件。

?52.png

php.ini的文件太多,找不到的時候你可以使用ctrl+f 搜索相關配置項。


53.png??


建議尺寸:?file_size(文件大小) < upload_max_filesize < post_max_size < memory_limit

另外,需要注意的是腳本執(zhí)行時間。

max_execution_time,這什參數(shù)的單位為秒。
這個參數(shù)是設定腳本的最大執(zhí)行時間。
也可以根據(jù)需求做適當?shù)母淖?。通常不需要來修改,系統(tǒng)默認值即可。超大文件上傳的時候,可能會涉及到這一項參數(shù)的修改。

上傳時間太長了,會超時。如果你將此項參數(shù)設為0,則是不限制超時時間,不建議使。

完成了php.ini的相關配置,我們就可以開始試著完成第一次文件上傳了。


三、文件上傳的步驟

為了更好的學習PHP,我們將極為復雜的PHP的文件上傳歸納總結(jié)成為了6個步驟。

在實際使用過程中,你按照這6個步驟就能夠很好的完成PHP的文件上傳:

1.判斷是否有錯誤碼

系統(tǒng)返回的錯誤碼詳解:


54.png


注:錯誤碼中沒有5

2.自定義判斷是否超出文件大小范圍

在開發(fā)上傳功能時。我們作為開發(fā)人員,除了php.ini中規(guī)定的上傳的最大值外。

我們通常還會設定一個值,是業(yè)務規(guī)定的上傳大小限制。

例如:
新浪微博或者QQ空間只準單張頭像圖片2M。而在上傳圖冊的時候又可以超過2M來上傳。

所以說,它的系統(tǒng)是支持更大文件上傳的。

此處的判斷文件大小,我們用于限制實際業(yè)務中我們想要規(guī)定的上傳的文件大小。

3.判斷后綴名和mime類型是否符合

在網(wǎng)絡世界里面也有壞人。他們會把圖片插入病毒,在附件中上傳病毒,他們會在網(wǎng)頁中插入病毒或者黃色圖片。

我們需要對于上傳的文件后綴和mime類型都要進行判斷才可以。

MIME(Multipurpose Internet Mail Extensions)是多用途互聯(lián)網(wǎng)郵件擴展類型。是設定某種擴展名的文件用一種應用程序來打開的方式類型,當該擴展名文件被訪問的時候,瀏覽器會自動使用指定應用程序來打開。多用于指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。

在判斷后綴和MIME類型的時候,我們會用到PHP的一個函數(shù)in_array(),該函數(shù)傳入兩個參數(shù)。
第一個參數(shù)是要判斷的值;
第二個參數(shù)是范圍數(shù)組。

我們用這個函數(shù)來判斷文件的后綴名和mime類型是否在允許的范圍內(nèi)。

4.生成文件名

我們的文件上傳成功了,不會讓它保存原名。
因為,有些人在原名中有敏感關鍵詞會違反我國的相關法律和法規(guī)。

我們可以采用date()、mt_rand()或者unique()生成隨機的文件名。

?

5.判斷是否是上傳文件

文件上傳成功時,系統(tǒng)會將上傳的臨時文件上傳到系統(tǒng)的臨時目錄中。產(chǎn)生一個臨時文件。

同時會產(chǎn)生臨時文件名。我們需要做的事情是將臨時文件移動到系統(tǒng)的指定目錄中。

而移動前不能瞎移動,或者移動錯了都是不科學的。移動前我們需要使用相關函數(shù)判斷上傳的文件是不是臨時文件。

is_uploaded_file()傳入一個參數(shù)($_FILES中的緩存文件名),判斷傳入的名稱是不是上傳文件

6.移動臨時文件到指定位置

臨時文件是真實的臨時文件,我們需要將其移動到我們的網(wǎng)站目錄下面了。

讓我們網(wǎng)站目錄的數(shù)據(jù),其他人可以訪問到。

我們使用:move_uploaded_file()。
這個函數(shù)是將上傳文件移動到指定位置,并命名。
傳入兩個參數(shù):
第一個參數(shù)是指定移動的上傳文件;
第二個參數(shù)是指定的文件夾和名稱拼接的字符串


四、文件上傳表單注意事項

我們開始正式的學習,學習如何來上傳文件。上傳文件必須在網(wǎng)頁中準備好一個form表單。

這是一個簡單的HTML頁面表單,form表單為文件內(nèi)容準備了一個專用的類,當input?里面?的 type=file 時,默認為上傳文件內(nèi)容。

我們來看一下表單的代碼和注意項

<html>
    <head>
        <meta charset="utf-8" />
        <title>單文件上傳</title>
    </head>
    <body>
        <form action="file.php" method="post" enctype="multipart/form-data">
            <input type="file" name="file">
            <input type="submit" value="上傳">
        </form>
    </body>
</html>

注:

  • form 表單中的參數(shù)method 必須為post。若為get是無法進行文件上傳的

  • ?enctype須為multipart/form-data


五、按照數(shù)組和步驟完成文件上傳

1.系統(tǒng)函數(shù)$_FILES

form表單提交的文件內(nèi)容指向了file.php。
我們在file.php中,通過PHP代碼,來處理上傳文件。

我們選擇一個名為圖片進行上傳。假設圖片的名字為:hua.jpg,點擊上傳。

PHP為文件類數(shù)據(jù)準備了一個專用的系統(tǒng)函數(shù)$_FILES,上傳文件的所有相關數(shù)據(jù),都保存在這個系統(tǒng)函數(shù)中。

在PHP文件中,我們打印 $_FILES ,來觀察這個數(shù)組的結(jié)構(gòu):

<?php
//var_dump()或print_r()
//打印變量的相關信息,將變量的信息詳細的展示出來
var_dump($_FILES);             
?>

打印出來的結(jié)果的數(shù)組結(jié)構(gòu)如下:

?55.png

得到了上面的數(shù)組結(jié)構(gòu)。

我們就可以開始文件的處理過程了。

2.判斷錯誤碼

<?php
if($_FILES['file']['error'] > 0){
    switch ($_FILES['file']['error']) {    //錯誤碼不為0,即文件上傳過程中出現(xiàn)了錯誤
        case '1':
            echo '文件過大';
            break;
        case '2':
            echo '文件超出指定大小';
            break;
        case '3':
            echo '只有部分文件被上傳';
            break;
        case '4':
            echo '文件沒有被上傳';
            break;
        case '6':
            echo '找不到指定文件夾';
            break;
        case '7':
            echo '文件寫入失敗';
            break;
        default:
            echo "上傳出錯<br/>";
    }
}else{
    //錯誤碼為0,即上傳成功,可以進行后續(xù)處理,處理流程見下文
}
?>

上面的代碼詳細的介紹了錯誤碼和對應的錯誤,我們可以根據(jù)錯誤碼,來生成準確的錯誤提示。

3.判斷文件是否超出大小

在實際項目中,由于系統(tǒng)硬件的限制,以及存儲設備的限制,不可能讓用戶無限制的上傳文件,所以我們要對用戶上傳的文件大小進行限制。定義一個合適的限制大小,能讓我們的應用更穩(wěn)定的運行。

//判斷錯誤
if($_FILES['file']['error'] > 0){
        //有錯誤可停止執(zhí)行
}else{
    //當前上傳文件無誤,運行本段代碼
 
    //判斷文件是否超出了指定的大小
    //單位為byte
    $MAX_FILE_SIZE = 100000;
    if($_FILES['file']['size'] > $MAX_FILE_SIZE){
    //判斷,如果上傳的文件,大小超出了我們給的限制范圍,退上傳并產(chǎn)生錯誤提示
        exit("文件超出指定大小");                           
    }

將我們指定的文件大小,定義為$MAX_FILE_SIZE,該變量的計數(shù)單位為byte,對應上傳文件的 $_FILES['file']['size']大小。
示例代碼中,限制大小約為100K及以下的文件。

4.判斷文件的mime類型是否正確

更多的時候,我們的文件上傳功能,都需要判斷用戶上傳的文件,是否符合要求,不可用的文件上傳以后,對于線上應用的整體展示效果,會造成惡劣的影響。所以我們需要通過mime類型和后綴名,來判斷用戶上傳的文件是否符合要求。

下面的示例代碼中,我們假設當前的項目需求為指定上傳圖片,要求上傳后綴名為GIF或者jpg的文件,當用戶上傳不符合要求的文件時,返回錯誤提示。

/*判斷后綴名和MIME類型是否符合指定需求
例如:
當前項目指定上傳后綴為.jpg或.gif的圖片,則$allowSuffix = array('jpg','gif');
*/
//定義允許的后綴名數(shù)組
$myImg = explode('.', $_FILES['file']['name']);         
 
/*
explode() 將一個字符串用指定的字符切割,并返回一個數(shù)組,這里我們將文件名用'.''切割,結(jié)果存在$myImg中,文件的后綴名即為數(shù)組的最后一個值
*/
$myImgSuffix = array_pop($myImg);
/*
根據(jù)上傳文件名獲取文件的后綴名
使用in_array()函數(shù),判斷上傳文件是否符合要求
當文件后綴名不在我們允許的范圍內(nèi)時退出上傳并返回錯誤信息
*/ 
if(!in_array($myImgSuffix, $allowSuffix)){                             
        exit("文件后綴名不符");
}
/*
mime類型和文件后綴名的對應關系,我們可以通過很多途徑查詢到,為了避免用戶自主修改文件后綴名造成文件無法使用。
mime類型也必須做出限制檢查mime類型,是為了防止上傳者直接修改文件后綴名
導致文件不可用或上傳的文件不符合要求。
*/
//數(shù)組內(nèi)容為允許上傳的mime類型
$allowMime = array(
            "image/jpg",
            "image/jpeg",
            "image/pjpeg",
            "image/gif"
            );
if(!in_array($_FILES['file']['type'], $allowMime)){                      //判斷上傳文件的mime類型是否在允許的范圍內(nèi)
      exit('文件格式不正確,請檢查');
    //如果不在允許范圍內(nèi),退出上傳并返回錯誤信息
}

5.生成指定的路徑和文件名

按照項目的文件安排,生成文件存儲路徑,為了避免文件名重復而產(chǎn)生的錯誤,按照一定的格式,生成一個隨機文件名。

//指定上傳文件夾
$path = "upload/images/";
/*
根據(jù)當前時間生成隨機文件名,本行代碼是使用當前時間 + 隨機一個0-9的數(shù)字組合成文件名,后綴即為前面取到的文件后綴名
*/
$name = date('Y').date('m').date("d").date('H').date('i').date('s').rand(0,9).'.'.$myImgSuffix;

6.判斷是否是上傳文件

is_uploaded_file()函數(shù)是專用的函數(shù),來判斷目標文件是否是上傳文件。

<?php
//使用is_uploaded_file()判斷是否是上傳文件,函數(shù)介紹見上文
if(is_uploaded_file($_FILEs['file']['tmp_name'])){    
}
?>

7.移動文件到指定位置

使用move_uploaded_file()函數(shù),將文件移動到指定的位置,并命名。需要注意的是,Linux系統(tǒng)中對目標目錄是否有權限及磁盤空間是否足夠,否則會導致上傳操作失敗。

/*
使用move_uploaded_file()移動上傳文件至指定位置,第一個參數(shù)為上傳文件,第二個參數(shù)為我們在前面指定的上傳路徑和名稱。
*/
 
if(move_uploaded_file($_FILEs['file']['tmp_name'], $path.$name)){
            //提示文件上傳成功
            echo "上傳成功";                                
        }else{
/*
文件移動失敗,檢查磁盤是否有足夠的空間,或者linux類系統(tǒng)中文件夾是否有足夠的操作權限
*/
            echo '上傳失敗';                                                
        }
    }else{
        echo '不是上傳文件';
    }
}
?>

完整代碼如下:

<?php
if ($_FILES['file']['error'] > 0) {
    switch ($_FILES['file']['error']) {
        //錯誤碼不為0,即文件上傳過程中出現(xiàn)了錯誤
        case '1':
            echo '文件過大';
            break;
        case '2':
            echo '文件超出指定大小';
            break;
        case '3':
            echo '只有部分文件被上傳';
            break;
        case '4':
            echo '文件沒有被上傳';
            break;
        case '6':
            echo '找不到指定文件夾';
            break;
        case '7':
            echo '文件寫入失敗';
            break;
        default:
            echo "上傳出錯<br/>";
    }
} else {

    $MAX_FILE_SIZE = 100000;
    if ($_FILES['file']['size'] > $MAX_FILE_SIZE) {
        exit("文件超出指定大小");

    }

    $allowSuffix = array(
        'jpg',
        'gif',
    );

    $myImg = explode('.', $_FILES['file']['name']);

    $myImgSuffix = array_pop($myImg);

    if (!in_array($myImgSuffix, $allowSuffix)) {
        exit("文件后綴名不符");
    }

    $allowMime = array(
        "image/jpg",
        "image/jpeg",
        "image/pjpeg",
        "image/gif",
    );

    if (!in_array($_FILES['file']['type'], $allowMime)) {
        exit('文件格式不正確,請檢查');
    }

    $path = "upload/images/";
    $name = date('Y') . date('m') . date("d") . date('H') . date('i') . date('s') . rand(0, 9) . '.' . $myImgSuffix;

    if (is_uploaded_file($_FILEs['file']['tmp_name'])) {

        if (move_uploaded_file($_FILEs['file']['tmp_name'], $path . $name)) {
            echo "上傳成功";
        } else {
            echo '上傳失敗';
        }

    } else {
        echo '不是上傳文件';
    }

}
?>

六、多文件上傳

介紹了PHP上傳單個文件的過程。但是有些時候,為了使用方便,我們需要滿足同時上傳多個文件的需求。多文件上傳原理相同,不過在處理數(shù)據(jù)時,需要對上傳數(shù)據(jù)進行特殊處理。

<html>
    <head>
        <meta charset="utf-8" />
        <title>單文件上傳</title>
    </head>
    <body>
        <form action="morefile.php" method="post" enctype="multipart/form-data">
         <input type="file" name="file[]">
         <input type="file" name="file[]">
         <input type="submit" value="上傳">
     </form>
    </body>
</html>

這里是一個簡易的上傳頁面,form表單同時提交了兩個文件。我們 可以通過這個頁面提交內(nèi)容。

注:

  • ?input type="file" name="file[]"與之前相比file后多加了一個中括號

  • 寫了2個或者多個input type="file" name="file[]"?
    我們使用 $_FILES 來接收文件信息,打印并查看數(shù)組:

<?php
var_dump($_FILES); //打印$_FILES查看數(shù)組結(jié)構(gòu)
?>

數(shù)組結(jié)構(gòu)如右所示

我們可以看到,兩個文件被存儲在一個數(shù)組中,鍵名和上傳單文件是相同。所以,需要我們用for()循環(huán),來分別取出兩個文件的需要用到的數(shù)據(jù)。

在$_FILES中同時保存了兩個文件的數(shù)據(jù),我們需要使用一個簡單的循環(huán),來讀取單個文件的信息,并將文件移動到我們想要放的位置。

for ($i=0; $i < count($_FILE['file']['name']); $i++) {  
/*
用is_uploaded_file()函數(shù)判斷是上傳文件
并且沒有出現(xiàn)錯
*/
    if(is_uploaded_file($_FILEs['file']['tmp_name'][$i]) && $_FILEs['file']['error'][$i] == 0){     
        if(move_uploaded_file($_FILEs['file']['tmp_name'][$i],'upload/'.$_FILE['file']['name'][$i])){
    //用move_uploaded_file()函數(shù)移動文件到指定的位置并使用文件原名
    echo "上傳成功";
        }else{
            echo '上傳失敗';
        }
    }else{
       echo '上傳失敗';
    }
}

詳細的判斷過程,參見單文件上傳,這里只做了基本的判斷,并沒有對文件的大小及格式提醒。?
請按照業(yè)務,自行判斷文件大小及格式進行錯誤提醒。


七、文件上傳進度處理

當文件過大,或者用戶網(wǎng)絡狀態(tài)一般,通常上傳過程需要一段時間,如果這時候讓用戶白屏等待的話,相信大部分用戶都會直接關掉應用,所以一個監(jiān)控上傳進度,并實時向用戶報告的需求就被產(chǎn)品汪擺在了桌面上。一個高逼格的上傳進度提示,會讓你的應用瞬間變成被仰望的存在。
PHP在5.4之前,總是需要安裝額外的擴展才能監(jiān)控到文件上傳進度。而從5.4開始,引入session.upload_progress的新特性,我們只需要在php.ini中開啟配置,即可通過session監(jiān)控文件上傳進度。在php.ini中。

注:本章學習需要有session基礎和javascript和ajax基礎。

我們需要配置,注意查看和修改php.ini文件:

56.png

開啟了配置,我們可以通過session,來記錄一個完整的文件上傳進度。在session中,會出現(xiàn)一個如下結(jié)果的數(shù)組:

 $_SESSION["upload_progress_test"] = array(
    //請求時間
     "start_time" => 1234567890,
     // 上傳文件總大小
     "content_length" => 57343257,
     //已經(jīng)處理的大小
     "bytes_processed" => 453489,
     //當所有上傳處理完成后為TRUE,未完成為false
     "done" => false,
 
     "files" => array(
      0 => array(
        //表單中上傳框的名字
 
       "field_name" => "file1",
 
       //上傳文件的名稱
       "name" => "test1.avi",
 
       //緩存文件,上傳的文件即保存在這里
       "tmp_name" => "/tmp/phpxxxxxx",
 
       //文件上傳的錯誤信息
       "error" => 0,
 
       //是否上傳完成,當這個文件處理完成后會變成TRUE
       "done" => true,
 
       //這個文件開始處理時間
       "start_time" => 1234567890,
 
       //這個文件已經(jīng)處理的大小
       "bytes_processed" => 57343250,     
      ),
 
      1 => array(
       "field_name" => "file2",
       "name" => "test2.avi",
       "tmp_name" => NULL,
       "error" => 0,
       "done" => false,                    
       "start_time" => 1234567899,
       "bytes_processed" => 54554,
      ),
     )
    );

這個數(shù)組詳細記錄了文件上傳的進度,已經(jīng)處理完的文件狀態(tài)為true。下面,我們通過一個jQuery的AJAX實例,來學習一下文件上傳進度的流程。

首先,在表單中,需要添加一個type=hidden 的 input 標簽,標簽 value 為自定義(建議使用有一定意義的值,因為這個值將要在后臺用到)

<form id="upload-form" action="upload.php" method="POST" enctype="multipart/form-data" style="margin:15px 0" target="hidden_iframe">
    <input type="hidden" name="<?php echo ini_get("session.upload_progress.name"); ?>" value="test" />
    <p><input type="file" name="file1" /></p>
    <p><input type="submit" value="Upload" /></p>
</form>
<div id="progress" style="margin-bottom:15px;display:none;">
    <div>0%</div>
</div>

這里,添加了一個ID為progress的div,作為展示上傳進度的容器。我們通過js的setTimeout(),定時執(zhí)行ajax來獲取文件上傳進度,后臺文件返回文件上傳的進度百分比。

<script src="../jquery/1.8.2/jquery.min.js"></script>
<script type="text/javascript">
function fetch_progress(){
    $.get('progress.php',{ '<?php echo ini_get("session.upload_progress.name"); ?>' : 'test'}, function(data){
        var progress = parseInt(data);
        $('#progress .label').html(progress + '%');
        if(progress < 100){
            setTimeout('fetch_progress()', 100);    //當上傳進度小于100%時,顯示上傳百分比
        }else{
            $('#progress .label').html('完成!'); //當上傳進度等于100%時,顯示上傳完成
        }
    }, 'html');
}
 
$('#upload-form').submit(function(){
    $('#progress').show();
    setTimeout('fetch_progress()', 100);//每0.1秒執(zhí)行一次fetch_progress(),查詢文件上傳進度
});
</script>

上面這段代碼,就是通過JQ的ajax,每0.1秒返回一次文件上傳進度。并把進度百分比在div 標簽中顯示。

后臺代碼,需要分為兩個部分,upload.php處理上傳文件。progress.php 獲取session中的上傳進度,并返回進度百分比。

這里文件上傳就不再贅述,詳細步驟參見上文,upload.php:

<?php
if(is_uploaded_file($_FILES['file1']['tmp_name'])){                                            //判斷是否是上傳文件
    //unlink($_FILES['file1']['tmp_name']);    
    move_uploaded_file($_FILES['file1']['tmp_name'], "./{$_FILES['file1']['name']}");     //將緩存文件移動到指定位置
}
?>
主要關注progress.php:
<?php
/*
開啟session。請注意在session_start()之前,請不要有想瀏覽器輸出內(nèi)容的動作,否則可能引起錯誤。
*/
 
session_start();
 
//ini_get()獲取php.ini中環(huán)境變量的值
$i = ini_get('session.upload_progress.name');
 
//ajax中我們使用的是get方法,變量名稱為ini文件中定義的前綴 拼接 傳過來的參數(shù)
$key = ini_get("session.upload_progress.prefix") . $_GET[$i];    
//判斷 SESSION 中是否有上傳文件的信息
if (!empty($_SESSION[$key])) {                                        
    //已上傳大小
    $current = $_SESSION[$key]["bytes_processed"];
    //文件總大小
    $total = $_SESSION[$key]["content_length"];
 
    //向 ajax 返回當前的上傳進度百分比。
    echo $current < $total ? ceil($current / $total * 100) : 100;
}else{
    echo 100;                                                       
}
?>

到這里,文件進度的代碼就已經(jīng)完成了,配合前端,我們就可以做一個炫酷的文件上傳功能啦!

學習心得:牢記文件上傳的六個步驟

?


繼續(xù)學習
||
<?php if ($_FILES['file']['error'] > 0) { switch ($_FILES['file']['error']) { //錯誤碼不為0,即文件上傳過程中出現(xiàn)了錯誤 case '1': echo '文件過大'; break; case '2': echo '文件超出指定大小'; break; case '3': echo '只有部分文件被上傳'; break; case '4': echo '文件沒有被上傳'; break; case '6': echo '找不到指定文件夾'; break; case '7': echo '文件寫入失敗'; break; default: echo "上傳出錯<br/>"; } } else { $MAX_FILE_SIZE = 100000; if ($_FILES['file']['size'] > $MAX_FILE_SIZE) { exit("文件超出指定大小"); } $allowSuffix = array( 'jpg', 'gif', ); $myImg = explode('.', $_FILES['file']['name']); $myImgSuffix = array_pop($myImg); if (!in_array($myImgSuffix, $allowSuffix)) { exit("文件后綴名不符"); } $allowMime = array( "image/jpg", "image/jpeg", "image/pjpeg", "image/gif", ); if (!in_array($_FILES['file']['type'], $allowMime)) { exit('文件格式不正確,請檢查'); } $path = "upload/images/"; $name = date('Y') . date('m') . date("d") . date('H') . date('i') . date('s') . rand(0, 9) . '.' . $myImgSuffix; if (is_uploaded_file($_FILEs['file']['tmp_name'])) { if (move_uploaded_file($_FILEs['file']['tmp_name'], $path . $name)) { echo "上傳成功"; } else { echo '上傳失敗'; } } else { echo '不是上傳文件'; } } ?>
提交重置代碼