本文目录导读:

- 使用 PHP 原生 Session 上传进度(PHP 5.4+)
- 使用 APC/Apcu 扩展(已废弃/较旧)
- 使用 JavaScript + XMLHttpRequest Level 2(推荐)
- 第三方库/方案(生产环境推荐)
- WebSocket + 专门的上传服务器(高级)
- 注意事项
- 总结建议
在PHP中获取上传进度是可以的,但实现方式取决于你的PHP版本和服务器配置。
主要有以下几种方法:
使用 PHP 原生 Session 上传进度(PHP 5.4+)
这是PHP内置的功能,不需要额外的扩展。
前置条件:
- PHP 5.4 或以上
session.upload_progress.enabled = On(默认开启)
实现步骤:
HTML 表单:
<form action="upload.php" method="post" enctype="multipart/form-data">
<!-- 关键:session.upload_progress.name 对应的隐藏字段 -->
<input type="hidden" name="<?php echo ini_get('session.upload_progress.name'); ?>" value="my_upload" />
<input type="file" name="file1" />
<input type="submit" value="上传" />
</form>
获取进度(progress.php):
<?php
session_start();
// 获取上传进度
$key = ini_get('session.upload_progress.prefix') . 'my_upload';
if (!empty($_SESSION[$key])) {
$progress = $_SESSION[$key];
echo json_encode([
'uploaded' => $progress['bytes_processed'],
'total' => $progress['content_length'],
'percentage' => round($progress['bytes_processed'] / $progress['content_length'] * 100)
]);
} else {
echo json_encode(['progress' => 0]);
}
前端轮询:
// 使用 AJAX 定时请求 progress.php
setInterval(function() {
fetch('progress.php')
.then(response => response.json())
.then(data => {
// 更新进度条
console.log('上传进度:' + data.percentage + '%');
});
}, 1000);
使用 APC/Apcu 扩展(已废弃/较旧)
APC 方法(PHP 5.x,已废弃):
<?php
// 在表单中需要设置:
// <input type="hidden" name="APC_UPLOAD_PROGRESS" value="unique_id" />
// 获取进度
$status = apc_fetch('upload_' . $_POST['APC_UPLOAD_PROGRESS']);
使用 JavaScript + XMLHttpRequest Level 2(推荐)
这是最通用、最可靠的方法,不需要服务器端额外配置。
const input = document.querySelector('input[type="file"]');
const formData = new FormData();
formData.append('file', input.files[0]);
const xhr = new XMLHttpRequest();
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const percent = (e.loaded / e.total) * 100;
document.querySelector('progress').value = percent;
console.log(`已上传 ${percent}%`);
}
});
xhr.addEventListener('load', () => {
console.log('上传完成');
});
xhr.open('POST', 'upload.php');
xhr.send(formData);
第三方库/方案(生产环境推荐)
Dropzone.js
<div id="myDropzone" class="dropzone"></div>
<script>
Dropzone.options.myDropzone = {
url: '/upload.php',
paramName: 'file',
maxFilesize: 2, // MB
dictDefaultMessage: "拖拽文件到这里上传",
init: function() {
this.on('uploadprogress', function(file, progress, bytesSent) {
console.log(file.name + ': ' + progress + '%');
});
}
};
</script>
Plupload
支持HTML5、Flash、Silverlight等多种上传方式,自带进度条。
WebSocket + 专门的上传服务器(高级)
对于大文件上传,可以使用:
- Resumable.js - 分块上传
- Tus - 可断点续传的开放协议
注意事项
| 问题 | 解决方案 |
|---|---|
| Nginx 缓冲问题 | 配置 proxy_buffering off 或使用 X-Accel-Buffering: no |
| Apache 模块问题 | 修改 mod_php 配置 |
| Session 并发锁 | 使用 session_write_close() 允许并行请求 |
| 内存限制 | 调整 memory_limit 和 upload_max_filesize |
总结建议
- 小项目/简单需求:使用 XMLHttpRequest Level 2(方法3),最简单且跨浏览器兼容
- 大文件/企业级应用:使用 Dropzone.js 或 Plupload 等成熟库
- 需要后端进度信息:使用 PHP Session 方法(方法1)
- 非常规需求(断点续传):使用 Tus 协议
最推荐的方案是 XMLHttpRequest Level 2,因为它:
- 实现简单
- 不需要服务器端配置
- 浏览器原生支持
- 不会消耗服务器额外资源