API流式导出大数据
<?phpnamespace App\Admin\Exports;use App\Admin\Services\Statistics\ExaminationRecordsDataService;
use App\Enums\ExaminationStatus;
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{$offset = 0;$chunkSize = 1000;$service = new ExaminationRecordsDataService();$this->search['sort'] = 'examination_records.id';$query = $service->getExaminationRecordsQuery($this->search)->limit($chunkSize);while (true) {$results = $query->clone()->offset($offset)->get();if ($results->isEmpty()) {break;}foreach($results as $item) {yield ['user_name' => $item->user_name,'group_name' => $item->group_name,'title' => $item->title,'course_serial_number' => $item->course_serial_number,'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, // 分钟];}$offset += $chunkSize;}}public function headings(): array{return ['user_name' => '姓名','group_name' => '所屬組織','title' => '所屬課程名稱','course_serial_number' => '所屬課程編號','name' => '考試名稱','serial_number' => '考試編號','examination_status' => '考試狀態','exam_nums' => '考試次數','total_score' => '總分','passing_score' => '通過分數','score' => '考試最高分','test_start_time' => '最高分考試的開始時間','test_end_time' => '最高分考試的結束時間','total_test_duration' => '考試規定時長(分鐘)','test_duration' => '最高分考試的進行時長(分鐘)',];}
}
<?phpnamespace 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', '512M');$search = $request->validated();$export = new ExaminationRecordExport($search);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://apitest-new-lms.wiltechs.com/api/admin/exampapers/questions/template?token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwOi8vYXBpdGVzdC1uZXctbG1zLndpbHRlY2hzLmNvbS9hcGkvYWRtaW4vYXV0aC9sb2dpbiIsImlhdCI6MTcwODQ3NzgyNiwiZXhwIjoxNzA4NTY0MjI2LCJuYmYiOjE3MDg0Nzc4MjYsImp0aSI6IlpuY0VqbWFVbUxnZ01FdVYiLCJzdWIiOiIxOEZENjAzQi03MjcwLTQyMkYtOTZDOS03M0U5QzQ0ODUyMzIiLCJwcnYiOiI3ZWJiOGEyY2MxZDk1YjYyYzk1OTRhMjJjOWNlYzIyZjM4ZGI1ZDMxIn0.D6Ie6QzG0Zm7Yw7nr1sOlaHon7noSY-2gyqpUfNXHfE';const a = document.createElement('a');
const event = new MouseEvent('click');
a.href = fileUrl;
// a.download = fileName;
a.dispatchEvent(event);
