优化增加第三方【每日推送】原始数据记录日志.log
This commit is contained in:
@@ -5,15 +5,19 @@ declare(strict_types=1);
|
||||
namespace app\common\library;
|
||||
|
||||
use app\common\model\MallDailyPush;
|
||||
use OpenSpout\Common\Entity\Row;
|
||||
use OpenSpout\Writer\XLSX\Options;
|
||||
use OpenSpout\Writer\XLSX\Writer;
|
||||
use support\Response;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* 每日推送数据导出(流式 CSV,兼容 Excel 打开)
|
||||
* 每日推送数据导出(OpenSpout 流式 XLSX)
|
||||
*/
|
||||
class MallDailyPushExport
|
||||
{
|
||||
public const MAX_EXPORT_LIMIT = 100000;
|
||||
/** 0 表示不限制条数,导出全部匹配数据 */
|
||||
public const UNLIMITED_EXPORT = 0;
|
||||
|
||||
public const CHUNK_SIZE = 2000;
|
||||
|
||||
@@ -64,28 +68,34 @@ class MallDailyPushExport
|
||||
throw new \InvalidArgumentException(__('Parameter error'));
|
||||
}
|
||||
|
||||
$limit = max(1, min(self::MAX_EXPORT_LIMIT, $limit));
|
||||
if ($limit < 0) {
|
||||
throw new \InvalidArgumentException(__('Parameter error'));
|
||||
}
|
||||
|
||||
@set_time_limit(0);
|
||||
|
||||
$exportDir = runtime_path('export');
|
||||
if (!is_dir($exportDir) && !mkdir($exportDir, 0755, true) && !is_dir($exportDir)) {
|
||||
throw new \RuntimeException('Failed to create export directory');
|
||||
}
|
||||
|
||||
$filepath = $exportDir . DIRECTORY_SEPARATOR . 'daily_push_' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . '.csv';
|
||||
$filepath = $exportDir . DIRECTORY_SEPARATOR . 'daily_push_' . date('YmdHis') . '_' . bin2hex(random_bytes(4)) . '.xlsx';
|
||||
$labels = $this->resolveFieldLabels($lang);
|
||||
$handle = fopen($filepath, 'wb');
|
||||
if ($handle === false) {
|
||||
throw new \RuntimeException('Failed to create export file');
|
||||
}
|
||||
|
||||
$options = new Options();
|
||||
$options->setTempFolder($exportDir);
|
||||
$writer = new Writer($options);
|
||||
|
||||
try {
|
||||
fwrite($handle, "\xEF\xBB\xBF");
|
||||
fputcsv($handle, $this->buildHeaderRow($fields, $labels));
|
||||
$writer->openToFile($filepath);
|
||||
$writer->addRow(Row::fromValues($this->buildHeaderRow($fields, $labels)));
|
||||
|
||||
$exported = 0;
|
||||
$page = 1;
|
||||
while ($exported < $limit) {
|
||||
$batchSize = min(self::CHUNK_SIZE, $limit - $exported);
|
||||
$unlimited = $limit === self::UNLIMITED_EXPORT;
|
||||
|
||||
while ($unlimited || $exported < $limit) {
|
||||
$batchSize = $unlimited ? self::CHUNK_SIZE : min(self::CHUNK_SIZE, $limit - $exported);
|
||||
$rows = $model
|
||||
->field($fields)
|
||||
->alias($alias)
|
||||
@@ -99,9 +109,9 @@ class MallDailyPushExport
|
||||
}
|
||||
|
||||
foreach ($rows as $row) {
|
||||
fputcsv($handle, $this->formatRow($row->toArray(), $fields));
|
||||
$writer->addRow(Row::fromValues($this->formatRow($row->toArray(), $fields)));
|
||||
$exported++;
|
||||
if ($exported >= $limit) {
|
||||
if (!$unlimited && $exported >= $limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -111,22 +121,27 @@ class MallDailyPushExport
|
||||
}
|
||||
$page++;
|
||||
}
|
||||
|
||||
$writer->close();
|
||||
} catch (Throwable $e) {
|
||||
fclose($handle);
|
||||
try {
|
||||
$writer->close();
|
||||
} catch (Throwable) {
|
||||
// ignore
|
||||
}
|
||||
if (is_file($filepath)) {
|
||||
@unlink($filepath);
|
||||
}
|
||||
throw $e;
|
||||
}
|
||||
|
||||
fclose($handle);
|
||||
register_shutdown_function(static function () use ($filepath): void {
|
||||
if (is_file($filepath)) {
|
||||
@unlink($filepath);
|
||||
}
|
||||
});
|
||||
|
||||
$filename = 'daily_push_' . date('YmdHis') . '.csv';
|
||||
$filename = 'daily_push_' . date('YmdHis') . '.xlsx';
|
||||
return (new Response())->file($filepath, $filename);
|
||||
}
|
||||
|
||||
@@ -157,7 +172,7 @@ class MallDailyPushExport
|
||||
|
||||
public function getMaxExportLimit(): int
|
||||
{
|
||||
return self::MAX_EXPORT_LIMIT;
|
||||
return self::UNLIMITED_EXPORT;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user