Export progress is adjusted to the rules shown in Excel’s actual export progress
1. The current Excel export progress is displayed by the front-end and is not controlled by the back-end. as shown in Figure 1
The decision is adjusted to display according to the actual export progress of Excel, and the final implementation rules are as follows:
Now exporting the Excel file, generally speaking, after the backend receives the front-end request, there are a total of 4 steps:
(1) Queue in the queue. In this link, the front-end progress always shows 0%
(2) Then when the queue job really starts, if the Excel is 10,000 rows, the progress increases by 9.9% for every 1000 rows written. When the write is complete, the progress is 99%
(3) Then it involves the processing of some column formats of Excel files, as well as uploading files to the cloud, generating download links, etc. After this link is completed, the front-end display progress is 100%
(4) After the front end obtains the download link, the download is successful. In this link, the progress is no longer displayed.
3. The final code implementation is roughly as follows
private string $cachedProgressPercentKey = 'job_status:progress_percent'; // 进度百分比的缓存键
private int $cachedProgressPercentTtl = 24 * 3600; // 进度百分比的缓存过期时间
public const EXPORT_EXCEL_WRITE_PROGRESS_PERCENT = 99; // 导出 Excel 时写入文件所占用的百分比
private int $exportExcelMaxCount = 100000; // 限制最大导出行数为 100000
private int $exportExcelChunkCount = 1000; // 导出时分块数量为 1000
// 更新进度百分比
$orderShippingLogCount = min($orderShippingLogQueryBuilder->count(), $this->exportExcelMaxCount);
$chunkCount = (int)ceil($orderShippingLogCount / $this->exportExcelChunkCount); // 上舍入
$i = 0;
$uid = $jobStatus->uid;
Log::info(
'$orderShippingLog',
[
'$orderShippingLogCount' => $orderShippingLogCount,
'$chunkCount' => $chunkCount,
]
);
$orderShippingLogQueryBuilder->chunk($this->exportExcelChunkCount, function ($orderShippingLogs) use ($params, $excel, $columns, $chunkCount, $uid, &$i) {
// 限制最大导出行数为 100000
if ($i >= $chunkCount) {
return false;
}
$data = [];
foreach ($orderShippingLogs as $rowKey => $orderShippingLog) {
$data[] = static::toResource($orderShippingLog, $params['timezone']);
}
$excel->writeRows($data);
// 更新进度百分比
$i++;
$progressPercent = ($i / $chunkCount) * JobStatusService::EXPORT_EXCEL_WRITE_PROGRESS_PERCENT;
app(JobStatusService::class)->setProgressPercent($uid, $progressPercent);
Log::info(
'$orderShippingLogChunk',
[
'$i' => $i,
'$chunkCount' => $chunkCount,
'$progressPercent' => $progressPercent
]
);
return true;
});
// 更新进度百分比
$jobStatusService->setProgressPercent($this->jobStatus->uid, 100);
/**
* 设置进度百分比
* @param string $uid
* @param float $progressPercent
* @return void
*/
public function setProgressPercent(string $uid, float $progressPercent): void
{
$cachedKey = sprintf($this->cachedProgressPercentKey . ':%s', $uid);
Cache::store('redis')->put($cachedKey, round($progressPercent, 2), $this->cachedProgressPercentTtl);
}
/**
* 获取进度百分比
* @param string $uid
* @return float
* @throws InvalidArgumentException
*/
private function getProgressPercent(string $uid): float
{
$cachedKey = sprintf($this->cachedProgressPercentKey . ':%s', $uid);
$cachedProgressPercent = Cache::store('redis')->get($cachedKey);
if (!$cachedProgressPercent) {
return 0;
}
return (float)$cachedProgressPercent;
}
4. The log printing is as follows:
[2024-05-10 07:33:35] local.INFO: $orderShippingLog {"$orderShippingLogCount":4696,"$chunkCount":5}
[2024-05-10 07:33:37] local.INFO: $orderShippingLogChunk {"$i":1,"$chunkCount":5,"$progressPercent":19.8}
[2024-05-10 07:33:40] local.INFO: $orderShippingLogChunk {"$i":2,"$chunkCount":5,"$progressPercent":39.6}
[2024-05-10 07:33:41] local.INFO: $orderShippingLogChunk {"$i":3,"$chunkCount":5,"$progressPercent":59.4}
[2024-05-10 07:33:42] local.INFO: $orderShippingLogChunk {"$i":4,"$chunkCount":5,"$progressPercent":79.2}
[2024-05-10 07:33:43] local.INFO: $orderShippingLogChunk {"$i":5,"$chunkCount":5,"$progressPercent":99}
5. The interface response structure is as follows
{
"label": "order",
"type": "export",
"status": "pending",
"file_path": "",
"progress_percent": 59.4
}
