如何在我的 React-Node.js 项目中添加 CSV 导入

Touch Base 很不错。这是一个很酷的项目。它成功了。但是,让我们面对现实吧——它有用吗?(Touch Base 是我制作的一款全栈 React 联系人管理应用)。

我思考了这个问题,意识到了一件显而易见的事情。当用户开始使用 Touch Base 时,他们必须手动添加联系人。如果你有 5 个联系人,这可能没问题。如果你想添加 1,000 个联系人,那就太糟糕了……你可能不想使用这个系统。所以当然,我知道我必须添加导入联系人的功能。

**研究选项**

我首先在 Google 上搜索的是“csv 导入器”或类似的东西。我浏览了一些可用的选项,找到了 FlatFile。他们的主标题是“收集、载入和迁移数据的最快方法”。完美……只是,对我来说并不是那么好。现在,这可能是我的错(他们似乎是一项很棒的服务),但实施他们的导入器的过程比我愿意为此付出的努力要多。这是介绍一些侧边栏背景的最佳时机:

最近,我非常重视勤奋。我想快速完成任务。这并不是为了偷工减料,我只是不想有任何借口或不必要的拖延。毕竟,我只是一个人在做副业。所以我现在的态度是失败、学习和快速迭代。同时做好工作。

回到 FlatFile。虽然我很想使用他们有前途的软件,但我问自己是否真的需要他们所有的花哨功能,以及与他们的文档作斗争是否值得。绝对不值得。所以我回到我的搜索并找到了 Papa Parse。我记得在之前的搜索中看到过它。他们的主标题是“适合大男孩和女孩的强大的浏览器内 CSV 解析器”。😆 我加入了。

**执行**

首先,我向我的 API 添加了一条 POST 路由。

'import-contacts API POST route'

`verifyToken` 是我在所有路由中使用的函数,它的作用就是验证用户 ID 令牌。我在我的应用程序中使用 multer,它是一个用于处理文件上传的 node.js 中间件。`upload.single('file')` 是一个 multer 函数,可帮助我将文件上传到我的 s3 存储桶。

在路线内部,我通过解构获取用户 ID 和文件。

code displaying the extraction of a user id and file properties from the request through the use of destructuring

就像 Papa Parse 的 npm 包文档所述,“在 Node.js 环境中使用时,Papa Parse 可以解析可读流而不是文件(除了纯字符串)。”

因此,我准备将文件直接传输到 Papa Parse,方法是从我的 s3 存储桶中创建上述流以及一个空数组来保存结果数据。不能忘记处理潜在的错误。

create a read stream of a file from an s3 bucket

然后我最终将流传递给 Papa Parse,设置我的配置选项并处理来自结果的任何错误。

passing the stream directly to Papa Parse

在上面的代码中,“complete”是 Papa Parse 的一个属性,它接受一个回调函数。解析完成后,它会执行。然后,我将“results”提供的数据作为“parsedData”保存起来。

此后,是时候在数据库上运行一些查询并处理联系人了。但是,我需要先存储数据库的连接以在其上运行查询。

code displaying the storing of a database connection

下一部分是 try catch 语句中的大量代码,因此我将直接提供给您一些注释。

processing and conditionally inserting contacts data into a PostgresQL database table

正如你所见,我

  • 获取现有联系人
  • 使用电子邮件过滤掉重复的联系人,因为没有两个电子邮件可以相同
  • 将非重复的联系人批量插入到表中
  • **前端**

    前端将主要针对我的应用程序方法,但让我们在这里连接各个点。

    导入联系人页面只做一件事,因此非常简单。我使用原生文件上传按钮,它实际上是一个输入。

    native input element that accepts .csv files and triggers a handling function

    当输入检测到变化时,我会触发“handleFileUpload”函数。

    在 `handleFileUpload` 函数内部,我首先将加载状态设置为 true,以便在此过程进行时可以向用户显示我的小型加载旋转器。

    code displaying a loading state being set to true at the beginning of a function

    当用户成功上传他们的 .csv 文件时,我会将其附加到新的 `formData` 对象并将其发送到上面的后端路由进行处理。我在这里直接使用获取请求,因为它是我的应用程序中唯一会到达 `/import-contacts` 端点的地方。如果我的应用程序的另一部分需要到达该路由,我会使用上下文存储请求并使用它来避免重复代码。此外,您可以看到我设置的错误处理……

    code displaying the sending of a file and handling of the response from an api endpoint

    一旦成功处理文件或者出现错误,加载状态就会被设置回 false,并且我会触发适当的 toast 警报,让用户以一种好的方式准确地知道发生了什么。

    登录、上传联系人 .csv 文件、收到成功提醒,然后看到帐户中填充的所有新联系人,这种感觉太棒了。而且速度非常快。您可能只会看到一秒钟的加载旋转器。批量插入查询也有很大帮助。

    从“或许可用”到“可用”

    在添加此功能之前,我想知道该应用程序到底有多好用。现在,毫无疑问。虽然它不是特别复杂,但它是您希望在这种类型的应用程序中看到的功能,所以我觉得这是实现的必要条件。我认为这让这个项目变得更加严肃。除此之外,我从未使用过 .csv 文件,这使得这项工作非常有趣。Papa Parse 与我已经使用的所有工具集成得非常好,这让它变得非常简单。我绝对推荐使用它。

    如果您读到了这一步,为您阅读此文而欢呼🥂...

    为不烂的软件干杯🥂

    我仍然想知道我的项目是否很糟糕😂

    如果您想查看,这里再次提供链接。

    下次见!