方案一:APC 擴展(需 PHP 5.4 以下,PHP 5.5+ 內建 OPcache 已移除 APC 用戶快取)
- 安裝:
pecl install apc
php.ini 設定:apc.rfc1867=1 啟用上傳進度追蹤。
- 前端表單需加入隱藏欄位:
<input type="hidden" name="APC_UPLOAD_PROGRESS" value="唯一ID" />(放在 <input type="file"> 之前)。
- 後端輪詢:
apc_fetch('upload_'.$_POST['APC_UPLOAD_PROGRESS']) 取得進度陣列(含 current, total, rate 等)。
if($_SERVER['REQUEST_METHOD']=='POST') {
$status = apc_fetch('upload_'.$_POST['apc_upload_progress']);
$status['done'] = 1;
echo json_encode($status);
exit;
} elseif(isset($_GET['progress_key'])) {
$status = apc_fetch('upload_'.$_GET['progress_key']);
echo json_encode($status);
exit;
}
方案二:uploadprogress 擴展(較輕量、專注上傳進度)
- 安裝:
pecl install uploadprogress
php.ini:uploadprogress.file.filename_template = "/tmp/upd_%s.txt"
- 表單隱藏欄位:
<input type="hidden" name="UPLOAD_IDENTIFIER" value="唯一ID" />
- 輪詢端點:
uploadprogress_get_info($_GET['sessid']) 回傳進度資訊。
if($_SERVER['REQUEST_METHOD']=='POST') {
if(is_uploaded_file($_FILES['upfile']['tmp_name'])) {
// 移動檔案、處理上傳完成邏輯
}
} elseif(!empty($_GET['sessid'])) {
header("Content-Type: application/json; charset=utf-8");
$info = uploadprogress_get_info($_GET['sessid']);
echo is_array($info) ? json_encode($info) : '{}';
exit;
}
現代替代方案
session.upload_progress(PHP 5.4+ 內建,無需額外擴展,需啟用 session.upload_progress.enabled=1)。
- 前端使用
XMLHttpRequest.upload.onprogress 或 fetch 配合 ReadableStream 直接顯示進度,無需後端輪詢。