Laravel Api流式导出大数据

API流式导出大数据

<?php

namespace App\Admin\Exports;

use App\Admin\Services\Statistics\ExaminationRecordsDataService;
use App\Enums\ExaminationStatus;
use App\Utilities\Conversion\VersionHelper;
use Generator;
use Maatwebsite\Excel\Concerns\FromGenerator;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithStrictNullComparison;

class ExaminationRecordExport implements FromGenerator, WithHeadings, WithStrictNullComparison
{
    private array $search;

    public function __construct(array $search)
    {
        $this->search = $search;
    }

    /**
     * @return Generator
     */
    public function generator(): Generator
    {
        $service = new ExaminationRecordsDataService();
        $this->search['sort'] = 'examination_records.id';
        $query = $service->getExaminationRecordsQuery($this->search);

        foreach($query->cursor() as $item) {
            yield [
                'user_name' => $item->user_name,
                'company_name' => $item->company_name,
                'department_name' => $item->department_name,
                'group_name' => $item->group_name,
                'position_name' => $item->position_name,
                'title' => $item->title,
                'course_serial_number' => $item->course_serial_number,
                'version' => VersionHelper::formatting($item->version),
                'name' => $item->name,
                'serial_number' =>$item->serial_number,
                'examination_status' => ExaminationStatus::from($item->examination_status)->label(),
                'exam_nums' => $item->exam_nums,
                'total_score' => $item->total_score,
                'passing_score' => $item->passing_score,
                'score' => $item->score,
                'test_start_time' => $item->test_start_time->format('Y-m-d H:i:s'),
                'test_end_time' => $item->test_end_time->format('Y-m-d H:i:s'),
                'total_test_duration' => $item->total_test_duration,
                'test_duration' => floor($item->test_duration / 60 * 100) / 100, // 分钟
            ];
        }
    }

    public function headings(): array
    {
        return [
            'user_name' => '姓名',
            'company_name' => '公司',
            'department_name' => '部門',
            'group_name' => '組別',
            'position_name' => '崗位',
            'title' => '所屬課程名稱',
            'course_serial_number' => '所屬課程編號',
            'version' => '版本號',
            'name' => '考試名稱',
            'serial_number' => '考試編號',
            'examination_status' => '考試狀態',
            'exam_nums' => '考試次數',
            'total_score' => '總分',
            'passing_score' => '通過分數',
            'score' => '考試最高分數',
            'test_start_time' => '最高分考試的開始時間',
            'test_end_time' => '最高分考試的結束時間',
            'total_test_duration' => '考試規定時長(分鐘)',
            'test_duration' => '最高分考試的進行時長(分鐘)',
        ];
    }
}

<?php

namespace App\Admin\Controllers;

use App\Admin\Exports\ExaminationRecordExport;
use App\Admin\Requests\Examination\GetExaminationRecordsListRequest;
use App\Admin\Resources\ExaminationRecord\ExaminationRecordCollection;
use App\Admin\Services\Statistics\ExaminationRecordsDataService;
use App\Traits\SearchStaffGroupTrait;
use App\Traits\SearchTrait;

class ExaminationController extends BaseController
{
    use SearchTrait, SearchStaffGroupTrait;

    public function getExaminationRecordsList(GetExaminationRecordsListRequest $request)
    {
        $search = $request->validated();
        $examinationRecords = (new ExaminationRecordsDataService())->getExaminationRecordsPage($search);
        return new ExaminationRecordCollection($examinationRecords);
    }

    public function export(GetExaminationRecordsListRequest $request)
    {
        set_time_limit(0);
        ini_set('memory_limit', '1024M');

        $search = $request->validated();
        $export = new ExaminationRecordExport($search);
        $total = (new ExaminationRecordsDataService())->getExaminationRecordsTotal($search);

        if ($total <= 10000) {
            return Excel::download($export, '學員考試記錄.xlsx');
        } else {
            header("Content-Type: application/force-download");
            header("Content-Type: application/octet-stream");
            header("Content-Type: application/download");
            header('Content-Disposition: attachment; filename=學員考試記錄.csv');
            header('Content-Type: text/csv; charset=gb18030');
            header("Content-Transfer-Encoding: binary");
            header("Pragma: no-cache");

            echo mb_convert_encoding(implode(',', array_values($export->headings())), 'gb18030') . "\n";
            foreach ($export->generator() as $item) {
                echo mb_convert_encoding(implode(',', array_values($item)), 'gb18030') . "\n";
            }
        }
    }
}
const fileUrl = 'https://api.xxx.com/...';

const a = document.createElement('a');
const event = new MouseEvent('click');
a.href = fileUrl;
// a.download = fileName;
a.dispatchEvent(event);

posted @ 2024-11-29 10:09  Tiac  阅读(3)  评论(0编辑  收藏  举报