(獨孤九劍)--文件上傳

【一】文件上傳javascript

場景:上傳博客,文章,圖片,人臉掃描等php

 

【二】配置文件css

(1)配置項   html

fille_uploads         開啓上傳功能on;關閉上傳功能off;前端

post_max_size     系統容許post傳參最大值java

upload_max_filesize    系統容許上傳文件最大值jquery

memory_limit               內存使用限制web

建議尺寸:上傳文件大小 < upload_max_filesize < post_max_size < memory_limit後端

(2)拓展數組

此外,還能夠配置臨時文件的存儲位置。

臨時目錄中的臨時文件有效期默認爲腳本週期,即一次請求結束

 

【三】表單數據類型

     表單數據類型有兩種:

     (1)字符串類型(字節流編碼);

     (2)文件類型(二進制編碼);

     *緣由解析*表單提交時:瀏覽器會默認的認爲,表單內數據都是字符串類型(即便使用file文件域)。經過在form上增長enctype屬性,告知瀏覽器表單內的數據不只有字符串,還有文件。從而進行文件提交

     上傳圖片和博客時須要設置上傳內容類型爲爲禁止編碼:multipart/form-data

      <form> 標籤的 enctype 屬性規定了在提交表單時要使用哪一種內容類型。在表單須要二進制數據時,好比文件內容,請使用 "multipart/form-data"

 

【四】提交時服務器處理方式

        接受瀏覽器請求時,處理好表單內數據。根據數據類型不一樣(2種),採用不一樣處理方式

        ①字符串類型/字節流,存儲在$_POST變量裏(內存裏)

        ②文件型數據/二進制,存儲在上傳臨時目錄中

 

【五】錯誤類型

每一個上傳的臨時文件都有 5個信息:name原始文件名;type類型;tmp_name臨時地址;error是否有錯及錯誤類型;size大小

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="提交" />
</form>
<?php
    echo "<pre>";
    var_dump($_FILES);
    echo "</pre>";
?>

提交後輸出數組:

array(1) {
  ["file"]=>
  array(5) {
    ["name"]=>
    string(10) "零食.txt"
    ["type"]=>
    string(10) "text/plain"
    ["tmp_name"]=>
    string(22) "C:\Windows\phpAD25.tmp"
    ["error"]=>
    int(0)
    ["size"]=>
    int(443)
  }
}

下面說下錯誤類型:01234567

0:無錯誤;

1:文件過大,大於PHP配置upload_max_filesize

2:文件過大,超過表單元素max_file_size

3:上傳部分文件

4:沒有上傳文件

5:上傳空文件

6:沒有找到臨時上傳文件(權限控制)

7:臨時文件寫入失敗

 

【六】案例:上傳預覽圖片

<!DOCTYPE html>
<html>
<head>
<title>PHP測試demo</title>
<link rel="stylesheet" href="./demo.css">
<style type="text/css">
 #preview{
            display: block;
            width: 100px;
            height: 100px;
            border:1px solid red;
 }
</style>
</head>
<body>
<form action="index.php" method="post" enctype="multipart/form-data">
<label for="file">文件名:</label>
<input type="file" name="file" id="file" />
<img id="preview" src=<?php echo "./upload/".$_FILES["file"]["name"]?> alt="點擊上傳圖片"/>
<br />
<input type="submit" name="submit" value="提交" />
</form>
<?php
//name原始文件名;type類型;tmp_name臨時地址;error是否有錯及錯誤類型;size大小
if ((($_FILES["file"]["type"] == "image/jpg")|| ($_FILES["file"]["type"] == "image/jpeg") || ($_FILES["file"]["type"] == "image/pjpeg"))){ if ($_FILES["file"]["error"] > 0){ echo "報錯: " . $_FILES["file"]["error"] . "<br />"; }else{ echo "文件名: " . $_FILES["file"]["name"] . "<br />"; echo "類型: " . $_FILES["file"]["type"] . "<br />"; echo "大小: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />"; echo "原先保存位置: " . $_FILES["file"]["tmp_name"]."<br>"; //保存 if (file_exists("./upload/" . $_FILES["file"]["name"])){ echo "注意:該文件". $_FILES["file"]["name"] . "已經存在!!!"; }else{ move_uploaded_file($_FILES["file"]["tmp_name"], "./upload/" . $_FILES["file"]["name"]); echo "提交後保存位置: " . "./upload/裏的" . $_FILES["file"]["name"]; } } }else{ echo "Invalid file文件類型不符"; }//注意路徑,例如../php7/a仍然是保存到php7裏,想要保存到php7下的a文件裏的話須要 路徑爲../php7/a/ ?> <script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.js"></script> <script type="text/javascript"> window.FileToSrc = function (file) { if (window.URL) return window.URL.createObjectURL(file); if (window.windcreateObjectURL) return window.createObjectURL(file); if (window.webkitURL) return window.webkitURL.createObjectURL(file); }; $('#file').on('change', function(){ //獲取文件列表對象 var fileList = $('#file')[0].files; //建立文件流獲取文件地址 var src =FileToSrc(fileList[0]); //設置圖片路徑 $("#preview").attr("src", src); }); </script> </body> </html>

 

【七】上傳步驟

(1)判斷是否有錯誤碼

$_FILES["file"]["error"]讀取錯誤類型

  0爲無錯誤,1234567爲有錯誤

if ($_FILES["file"]["error"] > 0){
    echo "報錯: " . $_FILES["file"]["error"] . "<br />";
}else{
    ...
}    

(2)自定義判斷文件大小是否超標

除了php.int中規定的上傳最大值外,一般還須要設定業務規定的上傳大小限制

例如:新浪微博或QQ空間頭像圖片規定限制2M,而上傳時又能夠超過2M

此處的判斷文件大小,用於限制實際業務裏想要規定的實際文件大小

(3)判斷後綴名和mime類型是否符合

黑客能夠在圖片裏植入病毒,在附件裏上傳病毒,會在網頁裏插入病毒或者誘惑性圖片。因此,咱們須要上傳文件後綴和mime類型都要進行判斷才行

mime類型是多用途互聯網郵件擴展類型,設定某種擴展名的文件用一種應用程序來打開的方式類型,當擴展文件名被訪問時,瀏覽器會自動使用指定應用程序來打開。多用於指定一些客戶端自定義的文件名,以及一些媒體文件打開方式。

在判斷後綴和MIME類型的時候,會用到PHP的in_array(判斷的值,範圍數組)函數,該函數須要用到兩個參數

咱們用in_array()來判斷文件的後綴名和mime類型是否在容許的範圍內

(4)生成文件名

文件上傳成功後,通常不會讓它保存原名。

由於有些人在原名裏添加了敏感關鍵詞,會違反國家相關法律

因此採用date()、mt_rand()、unique()生成隨機文件名

(5)判斷是不是上傳文件

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

<?PHP
header("content-type:text/html;charset=utf-8");
if(!empty($_FILES[up_picture][name])){                                       //判斷上傳文件是否爲空
    if($_FILES['up_picture']['error']>0){                                    //判斷文件是否能夠上傳到服務器
        echo "上傳錯誤";
        switch($_FILES['up_picture']['error']){
            case 1:
                echo "上傳文件大小超出配置文件規定值";
                break;
            case 2:
                echo "上傳文件大小超出表單中約定值";
                break;
            case 3:
                echo "上傳文件不全";
                break;
            case 4:
                echo "沒有上傳文件";
                break;
        }
    }else{
        if(!is_dir("./upfile/")){                                           //判斷指定目錄是否存在
            mkdir("./upfile/");                                             //建立目錄
        }
        $path='./upfile/'.time().strstr($_FILES['up_picture']['name'],'.');//定義文件名稱和存儲位置
        if(is_uploaded_file($_FILES['up_picture']['tmp_name'])){           //判斷是否經過HTTP POST上傳的
            if(!move_uploaded_file($_FILES['up_picture']['tmp_name'],$path)){       //執行上傳
                echo "上傳失敗";
            }else{
                echo "文件".time().$_FILES['up_picture']['name']."上傳成功,大小爲:".$_FILES['up_picture']['size'];
            }
        }else{
            echo "上傳文件".$_FILES['up_picture']['name']."不合法!";
        }
    }
}
?>

 

【八】步驟解析

(1)判斷錯誤碼

if ($_FILES['myfile']['error'] > 0) {
        switch ($_FILES['file']['error']) {
            case '1':
                echo "文件過大";
                break;
            case '2':
                echo "文件超出指定大小";
                break;
            case '3':
                echo "只上傳了部分文件";
                break;
            case '4':
                echo "沒有上傳文件";
                break;
            case '5':
                echo "上傳空文件";
                break;
            case '6':
                echo "沒有找到臨時上傳文件(權限問題)";
                break;
            case '7':
                echo "臨時文件寫入失敗";
                break;
        }
    }else{
        echo "無錯誤";
    }

(2)判斷文件是否超出大小

實際項目中因爲系統硬件的限制,以及存儲設備的限制,不可能讓用戶無限上傳文件。因此要對用戶上傳的文件大小進行限制,能讓應用平穩運行

將文件大小上限定義爲$MAX_FILE_SIZE,若文件大小大於$MAX_FILE_SIZE則退出上傳並錯誤提示

if ($_FILES['myfile']['error'] > 0) {
        exit("系統出錯0,1,2,3,4,5,6,7");
    }else{
        $MAX_FILE_SIZE = 1000;
        if ($_FILES['myfile']['size'] > $MAX_FILE_SIZE) {
            exit('文件超出指定大小');
        }
    }

(3)判斷文件的mime類型是否正確

例如要求上傳後綴名爲GIF或jpg的文件,當上傳不符合要求的文件時返回錯誤提示

注意:文件類型限制前端便可限制,後端也行

例如:要求只能上傳圖片

前端限制:選擇文件時只會出現圖片選項

<input type="file" name="myfile" id="file" accept="image/*"/>

後端限制:選擇文件時隨意,上傳時判斷進行限制

$allow = array('jpg','gif');//規定容許的類型
        $myImg = explode('.', $_FILES['myfile']['name']);//explode()將字符串打散爲數組
        $suffix = array_pop($myImg);//array_pop刪除數組末尾元素
        if (!in_array($suffix, $allow)) {
            exit("文件後綴名不符合");
        }else{
            echo "開始上傳";
        }

或者用數組簡單處理

$allow =array("image/jpg","image/jpeg","image/pjqeg","img/gif");
if (!in_array($_FILES['myfile']['type'], $allow)) {
      exit(文件格式不正確,請檢查);
}else{
      echo "開始上傳";
}

(4)生成指定文件路徑和文件名

爲了不文件名重複形成的錯誤,能夠按照必定格式生成隨機文件名

$path = "upload/imgs/";
$name = date('y').date('m').date('d').date('h').date('i').date('s').rand(0,9).'.'.'. $suffic';
//date('y').date('m').date('d').date('h').date('i').date('s')按照日期生成隨機數
//rand()生成指定範圍的隨機數

(5)判斷是否上傳文件

if (is_uploaded_file($_FILES['myfile']['tmp_name'])) {
    ...
}

(6)移動文件到指定位置

使用move_uploaded_file(filename, destination)將文件移動到指定位置保存

if(is_uploaded_file($_FILES['myfile']['tmp_name'])){
            if (move_uploaded_file($_FILES['myfile']['tmp_name'], $path. $name)) {
                echo "上傳成功";
            }else{
                echo "上傳失敗";
            }
        }else{
            echo "不是上傳文件";
        }

 

【九】多文件上傳

(1)可使用$_FILES來接受文件信息,打印並查看數組

<form action="" method="post" enctype="multipart/form-data">
    <input type="file" name="file[]"/><hr>
    <input type="file" name="file[]"/><hr>
    <input type="submit" name="submit" value="提交" />
</form>
<?php
    echo "<pre>";
    var_dump($_FILES['file']);
    echo "</pre>";
?>

(2)多文件時,從打印數據能夠看出文件信息被存到數組裏。這時須要用到循環來讀取單個文件的信息。

$array = $_FILES['file']['name'];
    $length = count($array);
    for($i=0;$i<$length;$i++){
        echo "文件名爲".$array[$i]."<br>";
        echo "原先保存位置: " . $_FILES["file"]["tmp_name"][$i]."<br>";
        move_uploaded_file($_FILES["file"]["tmp_name"][$i],"./upload/" . $array[$i]);
        echo "提交後保存位置: " . "./upload/裏的" . $array[$i]."<br>";
    }

注意:臨時文件名後需加[$i]來進行區分辨別

 

【十】文件上傳進度處理

在PHP的5.4版本以前,須要安裝額外的擴展才能監控到文件上傳進度。

5.4版本以後,引入了session.upload_progress的新特性,只須要在php.int裏開啓配置,便可經過session監控文件上傳進度

php.int裏配置項:

session.upoad_progress.enabled             是否啓用上傳進度報告(默認開啓,1開啓,0關閉)

session.upoad_progress.cleanup             是否在上傳完成後及時刪除進度數據(默認開啓,推薦開啓)

session.upload_progress.prefix[=upload_progress_]       進度數據存儲位置

session.upload_progress.freq[=1%]          更新進度的頻率(已經處理的字節數),也支持百分比表示%

session.upload_progress.min_freq[=1.0]   更新進度的時間間隔(秒數)

開啓配置後,能夠經過session,來記錄一個完整的文件上傳進度

代碼推薦網址:http://www.jb51.net/article/56305.htm

另外,UI使用一些插件上傳文件,就能夠獲取上傳進度,不用這麼麻煩,例如 Webuploader 

 

 

 

 

 

 

(拓展)

①MIME (Multipurpose Internet Mail Extensions) 多用途Internet郵件擴展,是描述消息內容類型的因特網標準

相關文章
相關標籤/搜索