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方法可以解决

 

 

posted @ 2022-02-07 13:00  wish_yang  阅读(448)  评论(0编辑  收藏  举报