业务场景
在业务进行数据分析时,会经常碰到导出数据的场景,而对于数据量较大的导出,使用Excel的方式导出会比较消耗性能,而csv是纯文本文件,但可通过Excel等软件打开,OSS支持文本文件上传,这满足了我们导出数据的需求,所以我们可以使用OSS+csv的方式进行大数据量的文件导出。
准备内容
- 已开通OSS服务
- Mysql数据库
- 下载OSS的SDK
PS:本文使用 PHP+Mysql 进行操作,大家可根据需要换成自己熟悉的语言和数据库。
操作步骤
- 分页从数据库获取数据
- 将数据上传至OSS
- 输出文件下载链接
示例代码:
use OSS\OssClient; use OSS\Core\OssException; /** * 生成csv文件 */ public function uploadCsvFile($content,&$position){ $accessKeyId = "your_access_key_id"; $accessKeySecret = "your_access_key_secret"; $endpoint = "oss-cn-qingdao.aliyuncs.com"; $bucket = "your_bucket_name";//请填入你的 OSS bucket 名称 $object = "/your_file_path/order_data.csv"; $object = $path.$fileName; $content = implode("\n", $content)."\n"; if ($position == 0) { //防止乱码 $content = "\xEF\xBB\xBF".$content; } try{ $ossClient = new OssClient($accessKeyId,$accessKeySecret,$endpoint); $position = $ossClient->appendObject($bucket,$object,$content,$position); } catch (OssException $e) { printf(__FUNCTION__ . ": FAILED\n"); printf($e->getMessage() . "\n"); return; } return $object; } public function exportData(){ $pageIndex = 1; $pageSize = 100; $position = 0; do{ //分页获取订单数据 $list = getOrderList($pageIndex,$pageSize); if (empty($list)) { break; } $content = []; if ($pageIndex == 1) { $content[] = ["用户名","订单号","下单时间","订单金额"]; } //将数据按照每行进行汇总 foreach ($list as $item) { $content[] = implode(',',[$item->user_name,$item->order_ID,$item->create_time,$item->price]); } //上传至OSS $filePath = $this->uploadCsvFile($content,$position); $pageIndex++; }while (true); } exportData();
因为使用Excel打开 csv 在不同系统打开会经常出现乱码的情况,比如 mac 上打开不乱码,但是在 windows 中打开就会出现乱码。这是因为在文件头缺少了 bom 头识别编码,打开时会按照系统默认的编码进行读取这时候就会出现乱码。所以我们在上传文件的起始位置要先插入UTF-8 bom 头( EF BB BF ),这样即可解决乱码问题。
关于导出我们还可以根据实际的业务需求进行一些拓展,比如通过异步的方式来实现导出,在用户的操作界面提供导出记录用于查看每个导出的进度,主要流程如下:
1、导出记录的数据表主要结构
字段名 |
说明 |
id |
主键 |
task_name |
导出任务 |
task_status |
任务状态:待导出、导出中、导出完成 |
user_id |
用户ID |
task_file |
导出结果文件 |
create_time |
创建时间 |
update_time |
更新时间 |
export_condition |
导出条件 |
2、导出流程
- 用户请求导出时,生成导出任务数据:任务名、任务状态(待导出)、用户ID、导出条件、创建时间
- 将生成的任务ID,作为消息内容发送到消息队列
- 后台接收消息后,根据任务ID获取导出条件,同时更新导出记录状态为“导出中”
- 根据导出条件分页查询,并将记录上传至OSS文件,将OSS的文件路径,记录到 task_file 字段中
- 数据导出结束,更新任务状态为“导出完成”,通知用户导出结果
此处的消息队列可使用阿里云的MNS、RocketMQ等消息队列产品。
结语
本文中的示例代码大家可以按照实际的需要进行调整,对于大批量的数据导出功能,可使用异步处理+消息通知的方式处理,可以减轻一部分的性能压力。