首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

PHP + AJAX 檔案上傳進度條實作:從原理到現成庫推薦

     編輯:程式設計綜合問答

核心原理

傳統 <input type="file"> 提交表單無法獲取進度。現代方案兩大類:

  1. XHR2 (XMLHttpRequest Level 2) — 原生 xhr.upload.onprogress 事件,無需外掛,IE10+ 全支援。
  2. Fetch API + ReadableStream — 更現代,但進度事件支援較晚 (Chrome 90+),兼容性略遜。

最小可運行範例 (原生 XHR2 + PHP)

<!-- HTML -->
<input type="file" id="fileInput" multiple>
<button onclick="uploadFiles()">上傳</button>
<div id="progressContainer"></div>

<script>
function uploadFiles() {
    const files = document.getElementById('fileInput').files;
    if (!files.length) return;
    const formData = new FormData();
    for (let f of files) formData.append('files[]', f);

    const xhr = new XMLHttpRequest();
    xhr.open('POST', 'upload.php', true);

    // 進度條 UI
    const container = document.getElementById('progressContainer');
    container.innerHTML = '';
    const bars = [];
    for (let i=0; i<files.length; i++) {
        const wrapper = document.createElement('div');
        wrapper.innerHTML = `${files[i].name}  0%`;
        container.appendChild(wrapper);
        bars.push(wrapper.querySelector('progress'));
    }

    xhr.upload.onprogress = e => {
        if (e.lengthComputable) {
            const pct = Math.round(e.loaded / e.total * 100);
            // 簡單平均顯示總進度,或依檔案索引分配
            bars.forEach((bar, idx) => {
                bar.value = pct;
                bar.nextElementSibling.textContent = pct + '%';
            });
        }
    };

    xhr.onload = () => {
        if (xhr.status === 200) alert('上傳成功:' + xhr.responseText);
        else alert('上傳失敗');
    };
    xhr.send(formData);
}
</script>
<?php
// upload.php
$uploadDir = __DIR__ . '/uploads/';
if (!is_dir($uploadDir)) mkdir($uploadDir, 0755, true);

$resp = [];
foreach ($_FILES['files']['tmp_name'] as $idx => $tmp) {
    $name = basename($_FILES['files']['name'][$idx]);
    $dest = $uploadDir . uniqid() . '_' . $name;
    if (move_uploaded_file($tmp, $dest)) {
        $resp[] = ['name' => $name, 'path' => $dest, 'status' => 'ok'];
    } else {
        $resp[] = ['name' => $name, 'status' => 'error'];
    }
}
header('Content-Type: application/json');
echo json_encode($resp);
?>

生產級推薦庫 (省去手工坑)

庫特點支援
blueimp/jQuery-File-Upload功能最全:分塊上傳、斷點續傳、圖片縮圖、拖曳、多語言jQuery, PHP/Node/Java/Go 後端範例
Uppy模組化、React/Vue/Svelte 友善、支援 Tus 協議 (斷點續傳標準)現代前端框架
DropzoneJS輕量、聲明式、預覽、進度、刪除、並發控制原生 JS / jQuery
Tus.io + 任意前端開放協議、斷點續傳標準、支援 S3/本地存儲跨語言、雲原生

常見坑點

  • PHP 設定: upload_max_filesize, post_max_size, max_execution_time, max_input_time 需配合大檔調大。
  • Nginx/Apache 限制: client_max_body_size (Nginx) / LimitRequestBody (Apache)。
  • Session 阻塞: PHP 預設 Session 檔案鎖導致並發上傳卡住,需 session_write_close() 或改用 Redis Session。
  • 安全: 驗證 MIME、副檔名、掃毒、重命名存儲、禁止直接訪問上傳目錄。

總結

原生 XHR2 寫進度條不到 50 行,適合輕量需求;專案若涉及大檔、斷點續傳、多框架整合,直接上 Uppy + Tus 或 blueimp,站在巨人肩膀上避坑。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved