Open jtwang7 opened 1 year ago
参考文章:
实现一个组件,其能够将本地 .csv 文件解析成对应的前端数据,不经由后台服务器处理。 总结而言就是:前端在线解析csv文件,并回显到前端。
.csv
借助 antd 的 <Upload /> 组件实现拖拽上传功能,同时调用 beforeUpload 钩子取消 antd 默认的文件上传逻辑。 借助 PapaParse.js 在前端解析 .csv 文件。
antd
<Upload />
beforeUpload
PapaParse.js
import { InboxOutlined } from "@ant-design/icons"; import { useBoolean } from "ahooks"; import { Upload, UploadProps } from "antd"; import { RcFile } from "antd/es/upload"; import _ from "lodash"; import Papa from "papaparse"; import { useEffect, useState } from "react"; import { Data, FileLoaderProps } from "./type"; export default function FileLoader(props: FileLoaderProps) { const { style, className, onChange, onLoading, onCompleted } = props; const { Dragger } = Upload; // 数据 const [data, setData] = useState<Data | null>(null); // 加载状态 const [loading, { setTrue, setFalse }] = useBoolean(false); // 是否加载完毕 const [completed, { setTrue: setCompleted, setFalse: setInitCompleted }] = useBoolean(false); const uploadProps: UploadProps = { accept: ".csv", directory: false, // 以文件 or 文件夹形式上传 multiple: true, // 是否支持多文件上传 showUploadList: false, // 是否展示上传文件的列表 beforeUpload: (file, fileList) => { const parser = (file: RcFile | RcFile[]) => { // 闭包保存当前的解析进度 const total = Array.isArray(file) ? file.length : 1; let completed = 0; return function fn(data = file) { // fn 用于解析文件 if (Array.isArray(data)) { // 若传入多文件,则递归解析 for (const f of data as RcFile[]) { fn(f); } } else { // 解析单文件 const f = data as RcFile; Papa.parse(f, { encoding: "utf-8", dynamicTyping: true, // 类型解析: string -> number / boolean header: true, // 保留 csv header complete(results, file) { const res = results.data; //去除最后的空行 有些解析数据尾部会多出空格 if (res[res.length - 1] === "") { res.pop(); } setData((prev) => { prev = !prev ? ({} as Data) : prev; completed += 1; Reflect.set(prev, f.name.split(".")[0], res); return _.cloneDeep(prev); }); // 数据加载完毕 if (completed === total) { setFalse(); setCompleted(); } }, }); } }; }; // 开始加载数据 - 初始化状态及数据 setTrue(); setInitCompleted(); setData(null); fileList.length ? parser(fileList)() : parser(file)(); // 中断 antd Upload 文件上传 return false; }, }; useEffect(() => { onChange?.(data); }, [data]); useEffect(() => { onLoading?.(loading); }, [loading]); useEffect(() => { onCompleted?.(completed); }, [completed]); return ( <Dragger {...uploadProps} style={{ width: "100%", height: "100%", ...style }} className={className} > <p className="ant-upload-drag-icon"> <InboxOutlined /> </p> <p className="ant-upload-text"> Click or drag file to this area to upload </p> <p className="ant-upload-hint"> Support for a single or bulk upload. Strictly prohibit from uploading company data or other band files </p> </Dragger> ); }
import { CSSProperties } from "react"; export type Data = { [key: string]: any[] }; export type FileLoaderProps = { style?: CSSProperties; className?: string; onChange?: (data: Data) => void; onLoading?: (status: boolean) => void; onCompleted?: (status: boolean) => void; };
本地 .csv 文件上传解析管理器实现:csv-loader
参考文章:
功能描述
实现一个组件,其能够将本地
.csv
文件解析成对应的前端数据,不经由后台服务器处理。 总结而言就是:前端在线解析csv文件,并回显到前端。思路
借助
antd
的<Upload />
组件实现拖拽上传功能,同时调用beforeUpload
钩子取消antd
默认的文件上传逻辑。 借助PapaParse.js
在前端解析.csv
文件。代码