PHP:大数据生成Excel导出下载
当一个大的数据需要生成并下载,通常会遇到两个问题。1,文件过大,2,查询太慢。
方法一:手动通过fputcsv流写文件。
优点:可写入数据量大,可导出百万数据。
缺点:不好抽取公共方法。
// 手动流式写入文件 // 设置不超时 set_time_limit(0); // Excel2003(xls)最大行列是65536行,256列 // Excel2007(xlsx)以后版本最大行列是1048576行,16384列(采取的是xml存储) // csv 本身无存储数量限制,但是使用excel打开就要受到excel的限制 $fileName = '文章.csv'; // 设置好告诉浏览器要下载excel文件的headers header('Content-Description: File Transfer'); header('Content-Type: application/vnd.ms-excel'); // 文件格式 header('Content-Disposition: attachment; filename="'.$fileName.'"'); // 文件名 header('Expires: 0'); // 有效期时间 header('Pragma: no-cache'); // 禁止缓存 $fp = fopen('php://output', 'a'); // 打开output流 $columns = ['文章ID','标题','作者']; mb_convert_variables('GBK', 'UTF-8', $columns); fputcsv($fp, $columns); // 将数据格式化为CSV格式并写入到output流中 $accessNum = 3000; // 从数据库获取总量 $perSize = 1000; // 每次查询的条数 $pages = ceil($accessNum / $perSize); $lastId = 0; // 这里根据查询的总页数分开查询,提高mysql查询效率 for($i = 1; $i <= $pages; $i++) { // $articleList = Article::get(['id','title','author'])->skip(($i-1)*$perSize)->take($perSize); // $articleList = Article::offset(($i-1)*$perSize)->limit($perSize)->get(['id','title','author']); $articleList = Article::where('id','>',$lastId)->limit($perSize)->get(['id','title','author']); foreach($articleList as &$data) { $rowData = [ $data->id,$data->title,$data->author ]; mb_convert_variables('GBK', 'UTF-8', $rowData); fputcsv($fp, $rowData); $lastId = $data->id; } // 释放变量的内存 unset($articleList); // 刷新输出缓冲到浏览器 ob_flush(); flush(); // 必须同时使用 ob_flush() 和flush() 函数来刷新输出缓冲。 } fclose($fp); exit();
方式二:laravel-excel 扩展插件,官网:https://docs.laravel-excel.com/3.1/getting-started/
优点:使用方便,有导入功能
缺点:查询数据需要放在一个变量里
// 1、安装 composer require maatwebsite/excel // 2、添加服务提供者 'providers' => [ ... ... Maatwebsite\Excel\ExcelServiceProvider::class, ] // 3、添加别名 'aliases' => [ ... 'Excel' => Maatwebsite\Excel\Facades\Excel::class, ] // 4、配置文件 php artisan vendor:publish --provider="Maatwebsite\Excel\ExcelServiceProvider" --tag=config // 5、创建1个导出类 php artisan make:export ArticleExport --model=Article // 需要实现 use Maatwebsite\Excel\Concerns\FromCollection 的Collection方法,下面提供案例 // 6、调用导出类 return Excel::download(new ArticleExport, 'articles.xlsx');
上面的导出类案例
<?php namespace App\Exports; use App\Models\Article; use Maatwebsite\Excel\Concerns\FromCollection; class ArticleExport implements FromCollection { /** * @return \Illuminate\Support\Collection */ public function collection() { return Article::all(); } } // 如果导出数组 需要实现的接口不一样 // class TestExport implements FromArray // { // private $id; // public function __construct($id) // { // $this->id = $id; // } // public function array(): array // { // $data = [[$this->id,$this->id,$this->id],[1,2,3],[4,5,6],[7,8,9]];//测试数据 // return $data; // } // }
方法三:fast-excel 扩展插件。参考:http://packagist.p2hp.com/packages/rap2hpoutre/fast-excel
优点:包小,使用方便,有导入功能
缺点:导出的数据量不够大
// fast-excel 包小,导出测试可以,下载不行 // 1、安装 composer require rap2hpoutre/fast-excel // 2、使用直接导入类 use Rap2hpoutre\FastExcel\FastExcel; // 3、生成数据 $articles = Article::all(); // Export all users download $export = (new FastExcel($articles))->export(config('filesystems.disks.public.root').'/file.xlsx'); // 4、手动调用response()->download方法可以解决