本文目录导读:

我来为您提供一个完整的PHP后台任务进度条实现方案。
前端HTML页面
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">任务进度条</title>
<style>
.progress-container {
max-width: 600px;
margin: 100px auto;
padding: 20px;
background: #f5f5f5;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.progress-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.progress-title {
font-size: 18px;
font-weight: bold;
color: #333;
}
.progress-percentage {
font-size: 16px;
color: #666;
font-weight: bold;
}
.progress-bar {
width: 100%;
height: 30px;
background: #e0e0e0;
border-radius: 15px;
overflow: hidden;
position: relative;
}
.progress-bar-fill {
height: 100%;
background: linear-gradient(90deg, #4CAF50, #45a049);
border-radius: 15px;
transition: width 0.3s ease;
width: 0%;
}
.progress-status {
margin-top: 20px;
padding: 10px;
background: white;
border-radius: 5px;
border: 1px solid #ddd;
font-size: 14px;
color: #666;
height: 40px;
overflow: auto;
}
.btn-group {
margin-top: 20px;
text-align: center;
}
.btn {
padding: 10px 30px;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
margin: 0 10px;
transition: all 0.3s;
}
.btn-start {
background: #4CAF50;
color: white;
}
.btn-start:hover {
background: #45a049;
}
.btn-start:disabled {
background: #cccccc;
cursor: not-allowed;
}
.btn-cancel {
background: #f44336;
color: white;
}
.btn-cancel:hover {
background: #da190b;
}
</style>
</head>
<body>
<div class="progress-container">
<div class="progress-header">
<div class="progress-title">任务进度</div>
<div class="progress-percentage" id="progressText">0%</div>
</div>
<div class="progress-bar">
<div class="progress-bar-fill" id="progressBar"></div>
</div>
<div class="progress-status" id="statusText">
等待任务开始...
</div>
<div class="btn-group">
<button class="btn btn-start" id="startBtn" onclick="startTask()">
开始任务
</button>
<button class="btn btn-cancel" id="cancelBtn" onclick="cancelTask()" style="display:none">
取消任务
</button>
</div>
</div>
<script>
let progressInterval = null;
let taskId = null;
// 开始任务
function startTask() {
document.getElementById('startBtn').disabled = true;
document.getElementById('cancelBtn').style.display = 'inline-block';
// 创建新的任务
fetch('start_task.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
action: 'start',
task_name: 'example_task'
})
})
.then(response => response.json())
.then(data => {
if (data.success) {
taskId = data.task_id;
document.getElementById('statusText').textContent = '任务开始...';
startProgressPolling();
} else {
alert('任务启动失败: ' + data.message);
}
});
}
// 开始轮询进度
function startProgressPolling() {
// 清除旧的轮询
if (progressInterval) {
clearInterval(progressInterval);
}
// 每1秒轮询一次进度
progressInterval = setInterval(() => {
getProgress();
}, 1000);
}
// 获取进度
function getProgress() {
if (!taskId) return;
fetch(`get_progress.php?task_id=${taskId}`)
.then(response => response.json())
.then(data => {
if (data.success) {
updateProgress(data.progress, data.status);
// 任务完成
if (data.progress >= 100) {
completeTask(data);
}
} else {
// 任务出错或不存在
errorTask(data);
}
})
.catch(error => {
console.error('获取进度失败:', error);
errorTask({message: '连接服务器失败'});
});
}
// 更新进度显示
function updateProgress(progress, status) {
document.getElementById('progressBar').style.width = progress + '%';
document.getElementById('progressText').textContent = progress + '%';
document.getElementById('statusText').textContent = status;
// 根据进度调整颜色
if (progress >= 100) {
document.getElementById('progressBar').style.background = '#4CAF50';
} else if (progress >= 70) {
document.getElementById('progressBar').style.background = '#ff9800';
} else if (progress >= 50) {
document.getElementById('progressBar').style.background = '#2196F3';
}
}
// 完成任务
function completeTask(data) {
if (progressInterval) {
clearInterval(progressInterval);
progressInterval = null;
}
document.getElementById('startBtn').disabled = false;
document.getElementById('cancelBtn').style.display = 'none';
document.getElementById('statusText').textContent = data.message || '任务完成!';
// 清理任务数据(可选)
setTimeout(() => {
fetch('cleanup_task.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ task_id: taskId })
});
}, 5000);
}
// 任务出错
function errorTask(data) {
if (progressInterval) {
clearInterval(progressInterval);
progressInterval = null;
}
document.getElementById('startBtn').disabled = false;
document.getElementById('cancelBtn').style.display = 'none';
document.getElementById('statusText').textContent = '错误: ' + data.message;
}
// 取消任务
function cancelTask() {
if (!taskId) return;
fetch('cancel_task.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ task_id: taskId })
})
.then(response => response.json())
.then(data => {
if (data.success) {
if (progressInterval) {
clearInterval(progressInterval);
progressInterval = null;
}
document.getElementById('startBtn').disabled = false;
document.getElementById('cancelBtn').style.display = 'none';
document.getElementById('statusText').textContent = '任务已取消';
document.getElementById('progressBar').style.width = '0%';
document.getElementById('progressText').textContent = '0%';
} else {
alert('取消任务失败');
}
});
}
</script>
</body>
</html>
后台PHP文件
start_task.php (启动任务)
<?php
header('Content-Type: application/json');
// 关闭错误显示,避免干扰JSON输出
error_reporting(0);
ini_set('display_errors', 0);
// 启用会话
session_start();
// 修改: 实现真正的后台任务
function start_background_task($task_name) {
// 生成唯一任务ID
$task_id = uniqid('task_', true);
// 创建进度文件
$progress_file = __DIR__ . '/tasks/progress_' . $task_id . '.txt';
if (!file_exists(dirname($progress_file))) {
mkdir(dirname($progress_file), 0777, true);
}
// 初始化进度
$initial_data = json_encode([
'progress' => 0,
'status' => '任务已启动',
'start_time' => time(),
'cancelled' => false
]);
file_put_contents($progress_file, $initial_data);
// 使用PHP CLI执行后台任务
$script = __DIR__ . '/background_task.php';
$php_path = PHP_BINARY; // 获取PHP解释器路径
// 在Windows上使用start,在Linux上使用nohup
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
// Windows命令
$command = 'start /B ' . escapeshellarg($php_path) . ' ' .
escapeshellarg($script) . ' ' .
escapeshellarg($task_id) . ' ' .
escapeshellarg($task_name) . ' > NUL 2>&1';
pclose(popen($command, 'r'));
} else {
// Linux命令
$command = 'nohup ' . escapeshellarg($php_path) . ' ' .
escapeshellarg($script) . ' ' .
escapeshellarg($task_id) . ' ' .
escapeshellarg($task_name) . ' > /dev/null 2>&1 &';
exec($command);
}
return $task_id;
}
// 处理请求
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
if (isset($input['action']) && $input['action'] === 'start') {
$task_name = isset($input['task_name']) ? $input['task_name'] : 'default_task';
// 检查是否已有任务在运行
if (isset($_SESSION['current_task_id'])) {
$prev_task = $_SESSION['current_task_id'];
$progress_file = __DIR__ . '/tasks/progress_' . $prev_task . '.txt';
if (file_exists($progress_file)) {
$data = json_decode(file_get_contents($progress_file), true);
if ($data && $data['progress'] < 100 && !$data['cancelled']) {
echo json_encode([
'success' => false,
'message' => '已有任务在运行中'
]);
exit;
}
}
}
// 启动新的后台任务
$task_id = start_background_task($task_name);
// 保存当前任务ID到会话
$_SESSION['current_task_id'] = $task_id;
echo json_encode([
'success' => true,
'task_id' => $task_id,
'message' => '任务启动成功'
]);
} else {
echo json_encode([
'success' => false,
'message' => '无效的操作'
]);
}
} else {
echo json_encode([
'success' => false,
'message' => '无效的请求方法'
]);
}
?>
background_task.php (后台任务处理)
<?php
// 后台任务脚本
error_reporting(E_ALL);
ini_set('display_errors', 0);
set_time_limit(0); // 不限制执行时间
// 获取参数
$task_id = isset($argv[1]) ? $argv[1] : '';
$task_name = isset($argv[2]) ? $argv[2] : 'default_task';
if (empty($task_id)) {
exit('Invalid task ID');
}
// 进度文件路径
$progress_file = __DIR__ . '/tasks/progress_' . $task_id . '.txt';
// 模拟长时间任务(实际应用中这里会是真实的业务逻辑)
function perform_task($task_id, $task_name, $progress_file) {
// 模拟任务总步骤
$total_steps = 100;
for ($step = 1; $step <= $total_steps; $step++) {
// 检查是否取消
if (file_exists($progress_file)) {
$data = json_decode(file_get_contents($progress_file), true);
if ($data && isset($data['cancelled']) && $data['cancelled']) {
update_progress($progress_file, $step, '任务已取消', true);
return 'cancelled';
}
}
// 模拟工作
sleep(1); // 1秒处理一步,总共约100秒
// 更新进度
$progress = round(($step / $total_steps) * 100);
$status = "正在处理第 {$step} 步 / 共 {$total_steps} 步";
update_progress($progress_file, $progress, $status);
// 随机模拟一些错误情况(可选)
if ($step == 50 && rand(0, 100) < 5) { // 5%的概率在第50步出错
update_progress($progress_file, 50, '任务出错:模拟错误', true);
return 'error';
}
}
// 任务完成
update_progress($progress_file, 100, '任务完成!');
return 'completed';
}
// 更新进度
function update_progress($file, $progress, $status, $is_error = false) {
$data = [
'progress' => $progress,
'status' => $status,
'last_update' => time(),
'cancelled' => isset($is_error) && $is_error ? true : false,
'completed' => $progress >= 100 || ($is_error && $progress < 100)
];
if ($progress >= 100) {
$data['completed'] = true;
$data['message'] = '任务完成!';
}
file_put_contents($file, json_encode($data));
}
// 执行任务
$result = perform_task($task_id, $task_name, $progress_file);
// 记录任务结果
if ($result === 'completed') {
echo "Task completed successfully\n";
} else if ($result === 'cancelled') {
echo "Task cancelled\n";
} else {
echo "Task failed\n";
}
?>
get_progress.php (获取进度)
<?php
header('Content-Type: application/json');
session_start();
error_reporting(0);
ini_set('display_errors', 0);
// 获取任务ID
$task_id = isset($_GET['task_id']) ? $_GET['task_id'] : '';
if (empty($task_id)) {
echo json_encode(['success' => false, 'message' => '任务ID无效']);
exit;
}
// 读取进度文件
$progress_file = __DIR__ . '/tasks/progress_' . $task_id . '.txt';
if (!file_exists($progress_file)) {
echo json_encode([
'success' => false,
'message' => '任务不存在或已过期'
]);
exit;
}
$data = json_decode(file_get_contents($progress_file), true);
if (!$data) {
echo json_encode([
'success' => false,
'message' => '无法读取任务进度'
]);
exit;
}
// 返回进度信息
echo json_encode([
'success' => true,
'progress' => $data['progress'],
'status' => $data['status'],
'message' => isset($data['message']) ? $data['message'] : ''
]);
?>
cancel_task.php (取消任务)
<?php
header('Content-Type: application/json');
session_start();
error_reporting(0);
ini_set('display_errors', 0);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
$task_id = isset($input['task_id']) ? $input['task_id'] : '';
if (empty($task_id)) {
echo json_encode(['success' => false, 'message' => '任务ID无效']);
exit;
}
// 更新任务状态为取消
$progress_file = __DIR__ . '/tasks/progress_' . $task_id . '.txt';
if (file_exists($progress_file)) {
$data = json_decode(file_get_contents($progress_file), true);
if ($data) {
$data['cancelled'] = true;
$data['status'] = '任务取消中...';
file_put_contents($progress_file, json_encode($data));
echo json_encode([
'success' => true,
'message' => '任务取消已触发'
]);
} else {
echo json_encode(['success' => false, 'message' => '任务数据无效']);
}
} else {
echo json_encode(['success' => false, 'message' => '任务不存在']);
}
} else {
echo json_encode(['success' => false, 'message' => '无效的请求方法']);
}
?>
cleanup_task.php (清理任务)
<?php
header('Content-Type: application/json');
error_reporting(0);
ini_set('display_errors', 0);
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$input = json_decode(file_get_contents('php://input'), true);
$task_id = isset($input['task_id']) ? $input['task_id'] : '';
if (!empty($task_id)) {
// 删除进度文件
$progress_file = __DIR__ . '/tasks/progress_' . $task_id . '.txt';
if (file_exists($progress_file)) {
unlink($progress_file);
// 可选的:删除其他相关文件
$log_file = __DIR__ . '/tasks/log_' . $task_id . '.txt';
if (file_exists($log_file)) {
unlink($log_file);
}
echo json_encode(['success' => true, 'message' => '任务数据已清理']);
} else {
echo json_encode(['success' => false, 'message' => '任务文件不存在']);
}
} else {
echo json_encode(['success' => false, 'message' => '任务ID无效']);
}
} else {
echo json_encode(['success' => false, 'message' => '无效的请求方法']);
}
?>
使用说明
-
创建目录结构:
mkdir -p /path/to/project/tasks chmod 755 /path/to/project/tasks
-
部署文件: 将所有PHP文件放在同一目录下,确保
tasks目录有正确权限。 -
安全建议:
- 添加身份验证
- 限制任务并发数
- 设置任务超时
- 清理过期任务文件
- 使用HTTPS传输
- 功能特点:
- ✅ 真正的后台任务执行
- ✅ 实时进度更新
- ✅ 任务取消功能
- ✅ 错误处理
- ✅ 跨平台兼容(Windows/Linux)
这个实现提供了一个完整的后台任务进度条方案,可以根据实际需求进行修改和扩展。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播