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

PHP 檔案上傳進度條實作:Session Upload Progress 完整教學

     編輯:PHP 綜合知識

核心機制

PHP 5.4+ 內建 Session Upload Progress,上傳過程中將進度資訊寫入 `$_SESSION`,前端透過 AJAX 輪詢即可顯示進度條,無需額外擴充套件。

php.ini 必要設定

; 必須啟用
session.upload_progress.enabled = On
session.upload_progress.cleanup = On
session.upload_progress.prefix = "upload_progress_"
session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS"
session.upload_progress.freq = "1%"
session.upload_progress.min_freq = "1"

完整範例(單檔)

<?php
session_start();

$prefix = ini_get('session.upload_progress.prefix');
$name = ini_get('session.upload_progress.name');
$key = $prefix . $name;

// AJAX 輪詢端點
if (isset($_POST['get_progress'])) {
    $progressKey = $prefix . $_POST['progress_name'];
    header('Content-Type: application/json');
    echo json_encode($_SESSION[$progressKey] ?? ['bytes_processed' => 0, 'content_length' => 0]);
    exit;
}

// 處理上傳
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) {
    // 這裡處理檔案儲存邏輯
    $targetDir = __DIR__ . '/uploads/';
    if (!is_dir($targetDir)) mkdir($targetDir, 0755, true);
    
    $filename = basename($_FILES['file']['name']);
    $targetPath = $targetDir . $filename;
    
    if (move_uploaded_file($_FILES['file']['tmp_name'], $targetPath)) {
        echo json_encode(['success' => true, 'message' => '上傳完成']);
    } else {
        http_response_code(500);
        echo json_encode(['success' => false, 'message' => '移動檔案失敗']);
    }
    exit;
}
?>
<!DOCTYPE html>
<html><head><meta charset="utf-8"><title>上傳進度示範</title>
<style>
.progress-bar {width:300px;height:20px;border:1px solid #ccc;border-radius:4px;overflow:hidden}
.progress-fill {height:100%;background:#4CAF50;width:0%;transition:width 0.3s}
</style></head><body>
<h2>檔案上傳進度條</h2>
<form id="uploadForm" enctype="multipart/form-data">
    <input type="hidden" name="<?= $name ?>" value="demo_upload">
    <input type="file" name="file" id="fileInput" required><br><br>
    <button type="submit">開始上傳</button>
</form>
<br>
<div class="progress-bar"><div class="progress-fill" id="progressFill"></div></div>
<div id="progressText">0%</div>

<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script>
const form = document.getElementById('uploadForm');
const progressFill = document.getElementById('progressFill');
const progressText = document.getElementById('progressText');
let pollTimer = null;

form.addEventListener('submit', async (e) => {
    e.preventDefault();
    const file = document.getElementById('fileInput').files[0];
    if (!file) return;
    
    const formData = new FormData(form);
    
    // 開始輪詢
    pollTimer = setInterval(async () => {
        try {
            const res = await axios.post('', {
                get_progress: 1,
                progress_name: 'demo_upload'
            });
            const data = res.data;
            if (data.content_length > 0) {
                const percent = Math.round((data.bytes_processed / data.content_length) * 10000) / 100;
                progressFill.style.width = percent + '%';
                progressText.textContent = percent + '%';
            }
        } catch (err) {
            console.error('輪詢失敗', err);
        }
    }, 500);
    
    // 執行上傳
    try {
        await axios.post('', formData, {
            headers: { 'Content-Type': 'multipart/form-data' },
            onUploadProgress: (e) => {
                // 瀏覽器原生進度(可作為備援)
            }
        });
        progressFill.style.width = '100%';
        progressText.textContent = '100% (上傳完成)';
    } catch (err) {
        progressText.textContent = '上傳失敗';
    } finally {
        clearInterval(pollTimer);
    }
});
</script>
</body></html>

關鍵點解析

設定/參數說明
session.upload_progress.name表單隱藏欄位 name,值作為進度識別碼
$_SESSION[$prefix . $value]進度資料結構:start_time, content_length, bytes_processed, done, files[]
freq更新頻率,1% 表示每 1% 更新一次 session
cleanup上傳完成後自動清除 session 進度資料

常見問題

  • 進度永遠 0%:確認 `session.upload_progress.enabled = On`、表單包含隱藏欄位、PHP 版本 ≥ 5.4
  • 大檔案上傳失敗:調整 `upload_max_filesize`、`post_max_size`、`max_execution_time`、`memory_limit`
  • Nginx 緩衝導致進度延遲:在 location 加入 `proxy_request_buffering off;`
  • 多檔上傳:每個檔案在 `files` 陣列中有獨立進度,需對應顯示

結語

Session Upload Progress 是 PHP 內建、零依賴的上傳進度方案,配合前端輪詢即可實現專業級進度條。注意 php.ini 設定與 Nginx 緩衝配置,即可穩定運作。

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