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

在项目开发过程中,读取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

第三步:pako安装

复制代码
npm install pako

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

复制代码
import pako from "pako";

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

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

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

复制代码
 const handleFile = (e) => {
        const file = e.target.files[0];

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

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

复制代码
const express = require("express");
const bodyParser = require("body-parser");
const cors = require("cors");
const pako = require("pako");

const app = express();

// 使用 cors 中间件处理跨域请求
app.use(cors());

// 使用 bodyParser 中间件解析请求体
app.use(bodyParser.raw({ type: "application/octet-stream", limit: "100mb" }));

// 处理 POST 请求
app.post("/", (req, res) => {
  // 获取压缩后的数据
  const compressedData = req.body;

  // 解压缩数据
  const uncompressedData = pako.ungzip(compressedData, { to: "string" });

  // 将解压缩后的数据解析为 JSON 对象
  const jsonData = JSON.parse(uncompressedData);

  // 打印压缩前数据长度,解压缩后数据长度和 JSON 对象长度
  console.log(
    compressedData.length,
    uncompressedData.length,
    jsonData.length
  );

  // 构造响应消息
  const msg =
    compressedData.length +
    " " +
    uncompressedData.length +
    " " +
    jsonData.length;

  // 发送响应
  res.status(200).send(msg);
});

// 启动服务器,监听端口 3000
app.listen(3000, () => {
  console.log("Server started on port 3000");
});

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

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

前端也已经返回了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秒左右,耗费时常比较久,那么随后我们会对其进行功能优化处理。

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

相关推荐
Xの哲學10 分钟前
Linux UPnP技术深度解析: 从设计哲学到实现细节
linux·服务器·网络·算法·边缘计算
柏木乃一14 分钟前
进程(6)进程切换,Linux中的进程组织,Linux进程调度算法
linux·服务器·c++·算法·架构·操作系统
Jelly-小丑鱼14 分钟前
Linux搭建SQLserver数据库和Orical数据库
linux·运维·数据库·sqlserver·oracal·docker容器数据库
Run_Teenage18 分钟前
Linux:进程等待
linux·运维·服务器
Trouvaille ~18 分钟前
【Linux】从磁盘到文件系统:深入理解Ext2文件系统
linux·运维·网络·c++·磁盘·文件系统·inode
为什么要内卷,摆烂不香吗27 分钟前
Grafana 12.2.0导入仪表盘
运维·grafana
乾元33 分钟前
AI 驱动的入侵检测与异常会话判别:从规则到行为分析前言:从“捕获敌人”到“守卫秩序”
运维·网络·人工智能·网络协议·安全
春日见35 分钟前
眼在手上外参标定保姆级教学(vscode + opencv)
linux·运维·服务器·数码相机·opencv·ubuntu·3d
娃乐呵1 小时前
免费的大批量Excel文档大模型处理数据工具
语言模型·大模型·excel·数据处理
梁下轻语的秋缘1 小时前
I2S与I2C
运维·stm32·单片机·51单片机