导出CSV文件

简介: 导出CSV文件

概述

优点

  • 支持流式写入,内存占用低,速度快。


缺点

  • 不能像Excel那样分Sheet
  • WPS在大约超过100万条的时候就打不开了
  • 特殊字符需要单独处理


最佳实践

  • 大量数据采用流式导出,少量数据没有必要采用流式导出的也没有必要上csv,采用导出Excel就行。
  • 每个csv文件的数据量不要超过50万条,如果一次导出的数据量过大,那么可以考虑导出多个csv文件,之后打一个压缩包给用户下载。


普通List方式导出

PostgreSQL stream导出

首先使用 pgpg-query-stream 包进行流式查询,得到数据库可读流,为 ReadStream 类型,示例:

import { ReadStream } from 'typeorm/platform/PlatformTools'; 
@Injectable()
export class CardService {
  constructor(@InjectRepository(CardEntity) private readonly cardRepository: Repository<CardEntity>) {}
  /**
   * 获取卡片列表流
   * @param sortType 正序or倒序
   * @param orderBy 排序依据
   * @param sn 卡片sn码(支持模糊搜索)
   */
  async findForExport(orderBy: string, sortType: SortType, sn?: string): Promise<ReadStream> {
    const queryConditionList = ['cards.deleted = false'];
    if (sn) queryConditionList.push('cards.sn LIKE :sn');
    switch (orderBy) {
      case 'sn':
        var order = 'sn';
        break;
      case 'productionDate':
        var order = 'production_date';
        break;
      default:
        var order = 'created_at';
    }
    return this.cardRepository
      .createQueryBuilder('cards')
      .where(queryConditionList.join(' AND '), { sn: `%c194a9eg<!-- begin-inline-katex{sn}%` })
      .orderBy(order, sortType)
      .stream();
  }
}
点击复制复制失败已复制


接下来创建一个文件写入流,通过fs.createWriteStream()方法创建,之后就是两个流对接,数据库流的数据经过转换后写入文件流中,当完成后关闭文件写入了,即可。


示例如下:

@Injectable()
export class XlsxUtil {
  /**
   * 流式导出
   * @param fileName csv文件名称
   * @param headers 表头列表
   * @param props 属性列表
   * @param data 数据流
   */
  exportCSV(fileName: string, headers: string[], props: string[], data: ReadStream): Promise<string> {
    return new Promise(async (resolve, reject) => {
      const filePath = join(__dirname, '../../../../public/temp/') + fileName;
      const writerStream = createWriteStream(filePath);
      writerStream.write('\uFEFF');
      writerStream.write(headers.join(','), 'UTF8');
      writerStream.write('\r\n', 'UTF8');
      data
        .on('data', data => {
          writerStream.write(
            props
              .map(prop => {
                if (data[prop] instanceof Date) return dayjs(data[prop]).format('YYYY-MM-DD HH:mm:ss');
                else if (prop.includes('_gender')) return data[prop] === Gender.Male ? '男' : '女';
                else if (prop === 'devices_active') return !datprop] || data[prop] === 'false' ? '未使用' : '使用中';
                return `"end-inline-katex-->{data[prop].replaceAll('"','""')}"`;    // csv文件格式处理
              })
              .join(','),
            'UTF8'
          );
          writerStream.write('\r\n', 'UTF8');
        })
        .on('close', () => {
          writerStream.end();
        });
      writerStream.on('finish', function() {
        return resolve('/public/temp/' + fileName);
      });
      writerStream.on('error', function(err) {
        return reject(err.stack);
      });
    });
  }
}点击复制复制失败已复制


注意

这里需要注意 csv 文件的数据格式,请转至笔记csv文件

上述高亮行中采用了 String.prototype.replaceAll() 方法,该方法是 ES2021 的语法,对于 node 来说,该方法从 node 16 LTS 开始支持,请注意node版本


导出代码解读

headers 是文件表头中的内容, propsPostgreSQL 数据库 ReadStreamdata 事件的回调内容中的字段列表,如下所示:

export const headers = ['标签编号', '生产日期', '备注', '类型', '创建时间'];
export const props = ['cards_sn', 'cards_production_date', 'cards_remark', '
目录
相关文章
|
9月前
|
Java Apache
导出csv格式的文件
导出csv格式的文件
90 0
|
Python Windows
csv文件
excel文件的后缀是.xls,它是二进制文件。 csv是文本文件,可用于excel打开,为人编写带来了方便。
1021 0
|
4月前
|
存储 Python
CSV文件
【10月更文挑战第18天】CSV文件
193 2
|
算法
CSV文件及其使用
在集图的过程中,你肯定会常常听到CSV文件这个词。那么所谓CSV文件到底是个什么东西呢? 它有什么用处呢?又要如何使用呢?认真读完下面的文字,相信你对CSV会有一个初步的了解。
1698 0
|
关系型数据库 测试技术 Windows
|
PHP JavaScript
导出csv文件时,处理分隔符问题(转)
转自:http://blog.sina.com.cn/s/blog_468530a60100kjpy.html   CSV文件默认以英文逗号做为列分隔符,换行符作为行分隔符。 如果不提供网页形式只用命令行或二进制程序输出数据到CSV,只需要将数据段按,分割,行按\n分割,写入到一个.csv文件即可。
4817 0
|
大数据 Shell 数据库管理
批量导出csv文件的基本尝试
   开发同学前几天给我提了一个数据查询的需求,大体是查询某个表的数据,然后把查询结果以csv的形式提供给他们,一般来说这种定制查询,开发的同学都会提供好语句,DBA同学只需要简单执行即可。
1091 0

热门文章

最新文章