• 前端实现csv文件的解析预览、上传、下载


    最近遇到了一些关于csv文件的上传、下载、解析预览、删除的需求。因为之前没有做过,尤其是关于csv的解析并预览,于是记录一下。

    上传

    关于上传,绝大部分的选择都是通过第三方的OSS进行存储,比如阿里云的。
    这个其实没什么难度,有文档可以看。对于前端来说,上传到OSS和上传给自己的后端,在过程上没什么区别,只是上传OSS多了一些配置项的参数。

    首先下载ossnpm
    npm install ali-oss --save

    顶部进行引入
    import OSS from 'ali-oss';

    上传的核心代码:

      const uploadFile = async (files, fileLists) => {
            const fileMaxSize = 1024 * 10;
            const fileType = ['csv', 'txt'];
            const { originFile: { size, name } } = files[0];
            const nameType = name.split('.')[1];
            if (size / 1024 > fileMaxSize) {
                Message('error', '文件过大!');
                return;
            };
            if (!fileType.includes(nameType)) {
                Message('error', '只支持csv和txt格式文件!');
                return;
            }
            const ossConfig = {
                region: 'oss-cn-xxxxxxx',
                accessKeyId: 'xxxxxxx',
                accessKeySecret: 'xxxxxxxxxx',
                bucket: 'xxxxx',
            };
            const client = new OSS(ossConfig);
            const { name: res_name, url } = await client.put(
                `xxxxxx/test/${v4()}.${nameType}`,
                files[0].originFile,
            )
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    其实需要的参数就是ossConfig这个对象,用来实例化引入的OSS

    • region,这个填写的是你买的oss资源的地区,比如oss-cn-beijing, 就是买的中国北京地区的资源
    • accessKeyIdaccessKeySecret,这两个是用来鉴权需要的密钥,我是像运维要的,估计是在阿里云后台里生成的
    • bucket,这个是你放到的根文件夹名字,一般就是你申请资源时的主体

    然后实例化出来的client就可以直接用了,一般都是用put方法,直接进行覆盖。传入的第一个参数是你要放到OSS的路径,比如creator/test/xxxx.csv,我这个名字为了避免重复,是用了一个uuid的,需要的可以自己下一下,还是比较好用的,理论上不会重复的一段字符串。
    npm install uuid --save
    import { v4 } from 'uuid'

    然后你就可以在返回值里拿到一系列的返回值了。

    前端实现文件上传到OSS,总体比较简单,配置一下参数之后,就跟正常的上传二进制文件一样了。

    下载

    下载也相对来说简单一下,先说下载,最后说预览解析。

    前端实现文件的下载,其实方法比较单一,基本都是通过动态创建a标签模拟点击来实现的。

    const downloadFile = async (name, url) => {
            console.log(name, url);
            const result = await fetch(url);
            const file = await result.blob();
            let a = document.createElement('a');
            let _url = window.URL.createObjectURL(file);
            let filename = name;
            a.href = _url;
            a.download = filename;
            a.style.display = 'none';
            document.body.appendChild(a);
            a.click();
            window.URL.revokeObjectURL(_url);
            document.body.removeChild(a);
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    因为文件是上传到了OSS,所以前端进行下载操作的前提是,先拿到这个文件的二进制流。

    先通过原生的fetch方法请求存在OSS的这个文件。然后通过查看原型链,可以找到这个blob方法,将返回值转为我们需要的二进制流。

    接下来的一系列操作就是通用的前端实现文件下载的代码:

    • 动态创建a标签
    • 通过window提供的createObjectURL将二进制流文件转为当前域名下的一段url
    • 然后将这个url赋值给a标签的href属性
    • 给这个要下载的文件起一个名字赋值给a标签的download属性
    • a标签隐藏,放入当前文档流中(可选)
    • 模拟click事件点击
    • 销毁url、销毁a标签

    总结下来,前端实现下载文件,其实在业务场景中很常见,实现方式也比较单一,先获取到要下载的文件二进制流、通过a标签实现下载。

    解析预览

    首先,我们需要知道,csv文件的特性,才可以进行解析。

    csv的内容其实就是形如下方的这个格式。
    username, password, nickname, age,,,
    creator, 123456, creator, 12,,,
    xiaozhang, 123456, xiaozhang, 12,,,
    所以,根据csv文件的特点,我们就可以进行解析和展示的,展示形式一般都是表格table

    默认情况下,我们认为csv的第一行数据是表头,所以,我们预期是将上面这段内容转为:

    [
    	{
    		username: 'creator',
    		password: '123456',
    		nickname: 'creator',
    		age: '12',
    	},
    	{
    		username: 'xiaozhang',
    		password: '123456',
    		nickname: 'xiaozhang',
    		age: '12',
    	}
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    进行数据转为的代码封装为一个函数。

    const formatCSV = (str) => {
    	let result = [];
    	let jsonObj = str.split(/((\r\n)|[\r\n])+/gi);
    	let arrHeader = [];
    	for (let i in jsonObj) {
    		if (typeof jsonObj[i] === 'string' && jsonObj[i].length > 0) {
    		let row = `${jsonObj[i]}`;
    	    if (row.trim().length > 0) {
    			const kv = jsonObj[i].split(',');
    			if (i === 0) {
    				arrHeader = kv;
    			} else {
    				const obj = {};
    				for (let index = 0; index < arrHeader.length; index ++) {
    					const name = String(arrHeader[index]);
    					if (!obj[name]) {
    						try {
    							if (kv[index]) {
    								obj[name] = String(kv[index]);
    							} else {
    								obj[name] = '';
    							}
    						} catch (err) {
    							obj[name] = '';
    						}
    					}
    				}
    				result.push(obj);
    			}
    		}	
    	  }
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
     const previewFile = async (url) => {
            const result = await fetch(url);
            console.log(result);
            const file = await result.blob();
    
            const reader = new FileReader();
            reader.onload = () => {
                const text = reader.result;
                const resultData = formatCSV(text);
                setPreviewData(resultData)
                setPreview(true);
            };
    
            reader.readAsText(file);
        };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    然后我们就可以拿到我们想要的格式的数据了。
    关于表格的展示,因为我用的是react + antdeisgn
    所以拼接出Table组件需要的datacolumn即可。
    data不需要额外处理,经过我们formatCSV返回的结果,就是我们需要的data

    column

    	let column = [];
    	for (let i in data[0]) {
    		column.push({
    			title: i,
    			dataIndex: i,
    		})
    	}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    <Table columns={tableColumn} data={tableData} /> 
    
    • 1

    ok,经过这一系列操作,就完成了我们既定的需求,关于csv文件的上传、下载、解析预览。

    总结

    最近工作中做了一些没接触过的需求,总结后给大家分享一下。在此之前我甚至不知道什么是csv的文件,只知道类似于excel的表格。做了这个需求知道,我知道了前端上传文件到OSS、前端下载OSS的文件、csv文件的本质格式、前端解析csv文件并预览展示。 经验就是在一个个未接触过的需求中增长的。

    QQ: 505417246
    WX: 18331092918
    公众号: Code程序人生
    B站账号: LuckyRay123
    个人博客: http://rayblog.ltd/
    欢迎关注我的各类账号, 持续更新优质前端内容

  • 相关阅读:
    Kaggle 知识点:物体检测赛题步骤
    【swift】struct与class 的区别
    《一个程序猿的生命周期》-《发展篇》- 46.2000万预算的项目,为什么跟踪15个月失败了
    计算矩阵边缘元素之和
    阿里二面:Java 序列化和反序列化为什么要实现 Serializable 接口?
    Android 富文本SpannableString
    C语言字符函数和字符串函数详解
    顺序表(删除)
    【OpenDDS开发指南V3.20】第五章:内容订阅配置文件
    Redis内存回收机制-内存淘汰策略和过期策略
  • 原文地址:https://blog.csdn.net/m0_46171043/article/details/126921233