前台实现csv文件下载思路

前台实现csv文件下载思路

  • 数据组装:将现有数据组装成csv文档格式类型,即逗号分隔每一列,换行符区分每一行
  • 数据Blob表示:用二进制大对象方式表示已组装数据,并创建URL引用
  • 前台触发机制:创建a标签或者img标签,利用其src能力触发前台下载
  • 内存释放:下载完成后,释放已创建的URL引用对象以及自定义的a标签或image标签

函数实现

参数说明:
表头部分:
headers = [{
    column:id,
    title:'索引',
    formatter:()=>{return ...}
}]
行数据:
rows = [{
    index: 0,
    userName: '',
    userAge: ''
}]
fileName: 导出文件名称

const getCsvBlob = (headers, rows) => {
    // 文件流开始标识
    const BOM = '\uFEFF'
    // 默认列分隔符
    const columnDelimiter = ','
    // 默认行分隔符
    const rowDelimiter = '\r\n'
    
    let csv = headers.reduce((previous, header) => {
        return (previous ? previous + columnDelimiter : '') + (header.title || header.column)
    }, '')
    if(Array.isArray(rows) && rows.length > 0){
        const columns = headers.map(header => header.column)
        csv = columns.reduce((previous, row) => {
            const rowCsv = columns.reduce((pre, column) => {
                if(Object.prototype.hasOwnProperty.call(row,column)){
                    let cell = row[column]
                    if(cell !== null){
                        const header = headers.find(item => item.column === column)
                        if(header.formatter !== null && typeof(header.formatter) === 'function'){
                            cell = header.formatter(cell)
                        }
                    }
                    if(cell !== null){
                        // 若数据中本来就含有行分隔符,则用''替换
                        cell = cell.toString().replace(new RegExp(rowDelimiter,'g'),'')
                        // 若数据中本来就含有列分隔符,则用''包起来'
                        cell = new RegExp(columnDelimiter).test(cell) ? `'${cell}'` : cell
                        // reduce初始值为'',故第一次迭代时不会再行首加列分隔符。后边的遇到值为空或不存在的列要填充含空格的空白' ',则pre返回true,会加列分隔符
                        return pre ? pre + columnDelimiter : pre + ''
                    } else {
                        // 即使不存在该列也要填充空白,避免数据和表头错位不对应
                        return pre ? pre + columnDelimiter : pre + ''
                    }
                    
                }
            },'')
            return previous + rowDelimiter + rowCsv
        },csv)
    }
    const blob = new Blob([BOM + csv], {
        type: 'text/csv;charset=utf-8;'
    })
    return blob
}
posted @ 2021-01-17 12:09  南华秋水  阅读(181)  评论(0编辑  收藏  举报