本地读取Excel文件并进行数据压缩传递到服务器

服务器 0

        在项目开发过程中,读取excel文件,可能存在几百或几百万条数据内容,那么对于大型文件来说,我们应该如何思考对于大型文件的读取操作以及性能的注意事项。

 类库:Papa Parse - Powerful CSV Parser for JavaScript

第一步:安装

npm install papaparse

第二步:内容的引入

import Papa from 'papaparse';import { useState } from "react";export default function App() {    const [results,setResults] = useState([]); //保留解析后的数据    const handleFile = (e) => {        const file = e.target.files[0];        Papa.parse(file,{            header:true, //指定第一行为标题行            skipEmptyLines:true, //跳过空行            complete:(parsedResult) => {                const data = parsedResult.data;                console.log(data) // 在控制台打印解析后的数据            }        })    };  return (    <div>        <h1>本地读取Excel文件并进行数据压缩传递到服务器</h1>        <input type="file" onChange={handleFile} accept='.csv' />    </div>  )}

当我们上传的数据为百万条数据的时候,数据量是非常的庞大的,那么如果将数据传输到服务器上,将会对http的请求资源产生极大的浪费。所以我们考虑使用第三方类库pako进行数据的压缩。

对于pako,可以查看以下文章进行一个了解:https://github.com/nodeca/pako

pako是什么以及它的的使用_如何使用pako库-CSDN博客文章浏览阅读62次。ws推送的gzip压缩能减少大量的传输数据,减少传输数据消耗,但是需要在收到数据之后解压。解压就可以用到pako了。_如何使用pako库https://blog.csdn.net/mantou_riji/article/details/135001065

%20

第三步:pako安装

%20
npm%20install%20pako
%20

第四步:在组件中进行pako引入且对数据进行gzip的压缩

%20
import%20pako%20from%20"pako";
%20

引入之后,将我们获取到的数据进行gzip的压缩

%20
//%20gzip压缩const%20gzip%20=%20pako.gzip(JSON.stringify(data),{to:"string"});console.log(JSON.stringify(data).length,gzip.length);%20//打印的则是压缩后的数据信息//原先的长度为41万,压缩后的长度为4万
%20

且发送到后端(以下是改事件的全部代码,gzip的压缩数据也在其内)

%20
%20const%20handleFile%20=%20(e)%20=>%20{%20%20%20%20%20%20%20%20const%20file%20=%20e.target.files[0];%20%20%20%20%20%20%20%20Papa.parse(file,{%20%20%20%20%20%20%20%20%20%20%20%20header:true,%20//指定第一行为标题行%20%20%20%20%20%20%20%20%20%20%20%20skipEmptyLines:true,%20//跳过空行%20%20%20%20%20%20%20%20%20%20%20%20complete:async%20(parsedResult)%20=>%20{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20data%20=%20parsedResult.data;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log(data)%20//%20在控制台打印解析后的数据%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20//%20gzip压缩%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20gzip%20=%20pako.gzip(JSON.stringify(data),{to:"string"});%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log(JSON.stringify(data).length,gzip.length);%20//打印的则是压缩后的数据信息%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20const%20response%20=%20await%20fetch("http://localhost:3000",{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20method:"POST",%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20body:gzip,%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20headers:{%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20"Content-Type":"application/octet-stream",%20//数据流的方式进行上传处理%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20});%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20console.log(response)%20%20%20%20%20%20%20%20%20%20%20%20}%20%20%20%20%20%20%20%20})%20%20%20%20};
%20

第五步:后端,后端也需要下载pako进行解压缩处理

%20
const%20express%20=%20require("express");const%20bodyParser%20=%20require("body-parser");const%20cors%20=%20require("cors");const%20pako%20=%20require("pako");const%20app%20=%20express();//%20使用%20cors%20中间件处理跨域请求app.use(cors());//%20使用%20bodyParser%20中间件解析请求体app.use(bodyParser.raw({%20type:%20"application/octet-stream",%20limit:%20"100mb"%20}));//%20处理%20POST%20请求app.post("/",%20(req,%20res)%20=>%20{%20%20//%20获取压缩后的数据%20%20const%20compressedData%20=%20req.body;%20%20//%20解压缩数据%20%20const%20uncompressedData%20=%20pako.ungzip(compressedData,%20{%20to:%20"string"%20});%20%20//%20将解压缩后的数据解析为%20JSON%20对象%20%20const%20jsonData%20=%20JSON.parse(uncompressedData);%20%20//%20打印压缩前数据长度,解压缩后数据长度和%20JSON%20对象长度%20%20console.log(%20%20%20%20compressedData.length,%20%20%20%20uncompressedData.length,%20%20%20%20jsonData.length%20%20);%20%20//%20构造响应消息%20%20const%20msg%20=%20%20%20%20compressedData.length%20+%20%20%20%20"%20"%20+%20%20%20%20uncompressedData.length%20+%20%20%20%20"%20"%20+%20%20%20%20jsonData.length;%20%20//%20发送响应%20%20res.status(200).send(msg);});//%20启动服务器,监听端口%203000app.listen(3000,%20()%20=>%20{%20%20console.log("Server%20started%20on%20port%203000");});
%20

执行以上操作后,我们运行项目选择文件,后端返回三条数据

%20

已压缩的长度 %20 未压缩的长度 %20 最终记录的条数

%20

前端也已经返回了response的一个相应数据

第六步:对打印的response进行进一步的处理 

console.log(response)const result = {    success:response.ok.toString(),    status:response.status,    message:response.statusText,};setResults(result)

第七步:展示到页面上

<h2>结果显示</h2><ul>    {results &&         Object.keys(results).map((key) => {            <li key={key}>                {key}:{results[key]}            </li>        })    }</ul>

第八步:添加一个点击按钮事件切换背景颜色

const toggleBodyBackground = () => {    if(document.body.style.background === "red"){        document.body.style.background = "white";    }else{        document.body.style.background = "red"    }}<button onClick={toggleBodyBackground}>change body background</button>

 当我进行大文件读取的时候会造成主线程的阻塞,那么后续我们可以进行功能的强化,在强化过程中,我们可以去考虑,是不是可以对现有的数据进行拆分,如果是一百多万条数据的时候,我们可以将一百多万条数据进行五万条,五万条的切片处理,然后不断的在后端进行压缩后数据的请求处理,最终可以在服务器端进行对数据的操作,减轻服务器的压力。

第九步:是否可以减轻服务器的压力,以下操作可以进行一个测试

使用console.time('test')开始时间设置console.timeEnd("test")结束时间设置

const handleFile = (e) => {    console.time('test') //开始时间    const file = e.target.files[0];    Papa.parse(file,{           ...............            };            setResults(result)            console.timeEnd("test"); //结束时间        }    })};

当前的测试时间为18秒左右,耗费时常比较久,那么随后我们会对其进行功能优化处理。

此内容已结束,希望对您有所帮助。 

也许您对下面的内容还感兴趣: