PHP+AJAX实现MySQL数据导入进度条不递增问题求助
问题解决:进度条无法逐步更新的修复方案
问题根源
- PHP会话阻塞:
actionImport执行时会持有PHP会话锁,导致后续的actionCheckImport请求被阻塞,直到导入脚本完全执行完毕,前端无法实时获取进度。 - 导入记录未标记状态:导入完成后未更新
TblNilaiTemp的status_sync字段,重复执行会导入相同数据,且进度统计逻辑不准确。 - 前端提示逻辑错误:每次检查进度都显示成功提示,不符合实际流程。
修改步骤
1. 后端actionImport修改
核心解决会话阻塞问题,同时优化导入逻辑:
public function actionImport() { // 释放会话锁,允许其他请求正常访问 session_write_close(); // 开启实时输出缓冲(用于调试,可选) ob_implicit_flush(true); ob_end_flush(); $model = TblNilaiTempEx::find() ->select([ 'tbl_nilai_temp.id as id_nilai_temp', 'tbl_nilai_temp.tbl_krs_id', 'tbl_nilai_temp.nilai_tugas', 'tbl_nilai_temp.nilai_praktek', 'tbl_nilai_temp.nilai_uts', 'tbl_nilai_temp.nilai_uas', 'tbl_nilai_temp.nilai_total', 'tbl_nilai_temp.nilai_huruf', 'tbl_nilai_temp.file_template_id' ]) ->from('tbl_nilai_temp') ->leftJoin('tbl_krs','tbl_krs.id=tbl_nilai_temp.tbl_krs_id') ->leftJoin('tbl_jadwal','tbl_jadwal.id=tbl_krs.tbl_jadwal_id') ->leftJoin('tbl_matakuliah','tbl_matakuliah.id=tbl_jadwal.tbl_matakuliah_id') ->leftJoin('tbl_kurikulum','tbl_kurikulum.id=tbl_matakuliah.tbl_kurikulum_id') ->leftJoin('tbl_program_studi','tbl_program_studi.id=tbl_kurikulum.tbl_program_studi_id') ->andWhere('tbl_matakuliah.tbl_matakuliah_jenis_id in (2,3,4,5,6) and tbl_nilai_temp.status_sync=0') ->asArray() ->limit(5) ->all(); foreach($model as $modelNilaiTemp) { $modelNilai = new TblNilaiEx; $modelNilai->tbl_krs_id = $modelNilaiTemp['tbl_krs_id']; $modelNilai->nilai_tugas = $modelNilaiTemp['nilai_tugas']; $modelNilai->nilai_praktek = $modelNilaiTemp['nilai_praktek']; $modelNilai->nilai_uts = $modelNilaiTemp['nilai_uts']; $modelNilai->nilai_uas = $modelNilaiTemp['nilai_uas']; $modelNilai->nilai_total = $modelNilaiTemp['nilai_total']; $modelNilai->nilai_huruf = $modelNilaiTemp['nilai_huruf']; $modelNilai->file_template_id = $modelNilaiTemp['file_template_id']; $modelNilai->tbl_nilai_rumus_id = 1; $modelNilai->status_eks = 4; $modelNilai->created_by = 1; $modelNilai->tbl_nilai_temp_id = $modelNilaiTemp['id_nilai_temp']; $result = $modelNilai->save(); // 标记原记录为已同步,避免重复导入 if ($result) { $nilaiTemp = TblNilaiTempEx::findOne($modelNilaiTemp['id_nilai_temp']); if ($nilaiTemp) { $nilaiTemp->status_sync = 1; $nilaiTemp->save(false); // 跳过验证提升效率 } echo "success\n"; } else { echo "Fail\n"; } // 强制刷新输出缓冲 flush(); ob_flush(); sleep(2); // 测试用,实际环境可移除 } }
2. 后端actionCheckImport修改
改为查询已同步的记录数,返回规范JSON格式:
public function actionCheckImport() { // 统计已完成同步的记录数 $count = TblNilaiTempEx::find() ->andWhere('status_sync=1') ->count(); // 返回JSON响应 Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; return ['count' => $count]; }
3. 前端JS修改
适配JSON响应,优化进度提示逻辑:
<?php $js = <<<JS var clear_timer; $('.sync-form').submit(function(event) { $('#message').html(''); event.preventDefault(); event.stopImmediatePropagation(); // 总数据数建议从后端接口动态获取,此处暂用硬编码 var total_data = 5; $('#total_data').text(total_data); clear_timer = setInterval(function() { check_imported_data(total_data); }, 1000); $.ajax({ url:"/sync-nilai-ta/import", method:"POST", data: new FormData(this), contentType:false, cache:false, processData:false, beforeSend:function(){ $('#sync-button').attr('disabled','disabled'); $('#sync-button').val('Synchronizing'); }, complete:function(){ $('#sync-button').val('Sync'); $('#sync-button').removeAttr('disabled'); } }); }); function check_imported_data(total_data) { $.ajax({ url:"/sync-nilai-ta/check-import", dataType:"json", success:function(response) { var imported_count = response.count; var width = Math.round((imported_count / total_data) * 100); $('#process_data').text(imported_count); $('.progress-bar').css('width', width + '%').attr('aria-valuenow', width); // 仅当全部完成时显示成功提示 if(imported_count >= total_data ) { clearInterval(clear_timer); $('#message').html('<div class="alert alert-success">Data Successfully Imported</div>'); } } }); } JS; $this->registerJs($js); ?>
关键说明
- 会话锁释放:
session_write_close()是解决进度阻塞的核心,它会释放PHP会话锁,让后续的进度检查请求能正常执行。 - 状态标记:更新
status_sync字段既避免重复导入,也让进度统计更准确。 - 前端逻辑优化:修正提示时机,适配JSON响应格式,确保进度条逐步递增更新。
内容的提问来源于stack exchange,提问作者eniac05
相关产品推荐
相关产品推荐

