AJAX檔案上傳並顯示進度條(案例實戰)

2020-07-16 10:05:13
本例需要 PHP 伺服器虛擬環境,同時在站點根目錄下新建 upload 資料夾,然後在站點根目錄新建前台檔案 test1.html,以及後台檔案 test.php。在上傳檔案時,使用 XMLHttpRequest 動態顯示檔案上傳的進度。

test.html

<script type="text/javascript">
    function fileSelected(){
    var file = document.getElementById('fileToUpload').files[0];
    if(file){
        var fileSize = 0;
        if(file.size>1024*1024){
            fileSize=(Math.round(file.size*100 / (1024*1024)) / 100).toString()+'MB';
        } else {
            fileSize=(Math.round(file.size * 100 / 1024) / 100).toString()+'KB';
        }
        document.getElementById('fileName').innerHTML = '檔名:'+ file.name;
        document.getElementById('fileSize').innerHTML = '大小:'+ fileSize;
        document.getElementById('fileType').innerHTML = '型別:' + file.type;  
        }
    }
    function uploadFile(){
        var fd = new FormData();
        fd.append("fileToUpload",document.getElementById('fileToUpload').files[0]);
        var xhr = new XMLHttpRequest();
        xhr.upload.addEventListener("progress",uploadProgress,false);
        xhr.addEventListener("load",uploadComplete,false);
        xhr.addEventListener("error",uploadFailed,false);
        xhr.addEventListener("abort",uploadCanceled,false);
        xhr.open("POST","test.php");
        xhr.send(fd);
    }
    function uploadProgress(evt){
        if(evt.lengthComputable){
            var percentComplete = Math.round(evt.loaded * 100 / evt.total);
            document.getElementById('progressNumber').innerHTML = percentComplete.toString() + '%';
        } else {
            document.getElementById('progressNumber').innerHTML = 'unable to compute';
        }
    }
    function uploadComplete(evt){
        var info = document.getElementById('info');
        //當伺服器傳送響應時,會引發次事件
        info.innerHTML = evt.target.responseText;
    }
    function uploadFailed(evt){
        console.log("檢視上載檔案時出現一個錯誤");
   }
   function uploadCanceled(evt){
        console.log("上傳已被使用者取消或瀏覽器放棄連線");
    }
 </script>
<form id="form1" enctype="multipart/form-data" method="post" action="upload.php">
    <div class="row">
        <label for="fileToUpload">選擇上傳檔案</label>
        <input type="file" name="fileToUpload" id="fileToUpload" onchange="fileSelected()" />
    </div>
    <div id="fileName"></div>
    <div id="fileSize"></div>
    <div id="fileType"></div>
    <div class="row">
        <input type="button" onclick="uploadFile()" value="上傳" />
   </div>
   <div id="progressNumber"></div>
   <div id="info"></div>
  </form>

test.php

<?php
    header("content:text/html; charset=utf-8");
    $uf = $_FILES['fileToUpload'];
    if(!$uf){
     echo '沒有 filetoupload 參照';
     exit();
    }
    $upload_file_temp = $uf['tmp_name'];
    $upload_file_name = $uf['name'];
    $upload_file_size = $uf['size'];
    if(!$upload_file_temp){
     echo "上傳失敗";
     exit();
    }
    $file_size_max = 1024 * 1024 * 100;
    //檢查檔案大小
    if ($upload_file_size > $file_size_max) {
        echo "對不起,您的檔案容量超出允許範圍:".$file_size_max;
        exit();
    }
    $store_dir = "./upload/";
    $accept_overwrite = 0;
    $file_path = $store_dir.$upload_file_name;
    //檢查讀寫檔案
    if (file_exists($file_path) && !$accept_overwrite) {
        echo "存在相同檔名的檔案";
        exit();
    }
    //複製到指定目錄
    if (!move_uploaded_file($upload_file_temp, $file_path) {
        echo "複製檔案失敗".$upload_file_temp."to".$file_path;
        exit();
    }
    Echo "<p>您上傳了檔案:";
    echo $upload_file_name;
    echo "<br>";
    //用戶端機器檔案的原名稱
    Echo "檔案的 MIME 型別為:";
    echo $uf['type'];
    //檔案的IMIE型別,需要瀏覽器提供該資訊的支援,如image/gif
    echo "<br>";
    Echo "上傳檔案大小";
    echo $uf['size'];
    //已上傳檔案的大小,單位為位元組
    echo "<br>";
    Echo "檔案上傳後被臨時儲存為:";
    echo $uf['tmp_name'];
    //檔案被上傳後在伺服器端儲存的臨時檔名
    echo "<br>";
    $error =  $uf['error'];
    switch ($error) {
    case 0 :
        Echo "上傳成功"; break;
    case 1 :
        Echo "上傳的檔案超過了 php.ini 中 upload_max_filesize 選項限制的值。"; break;
    case 2 :
        Echo "上傳檔案的大小超過了 HTML 表單中 MAX_FILE_SIZE 選項指定的值。"; break;
    case 3 :
        Echo "檔案只有部分被上傳"; break;
    case 4 : 
        Echo "沒有檔案被上傳"; break;
?>
演示效果如下: