在Node.js中使用FilePond的教程

269 阅读7分钟

如何在Node.js中使用FilePond

FilePond为JavaScript应用程序带来了简单而强大的文件上传功能,而且是免费的开源。下面是如何在Node.js的Express后端使用它。

上传文件是云计算应用的一个普遍需求。FilePond是一个可靠的开源项目,它为ReactSvelte等许多JavaScript框架提供了复杂的文件处理和包装。

本文概述了用FilePond和Node.js及Express后端处理文件上传的情况。

[InfoWorld上还有:如何用Node.js和MongoDB进行CRUD] 。

为什么是FilePond?

有许多库可用于该任务,但 FilePond 极其容易使用,并且无需额外配置即可处理图像优化等细微问题。此外,它在服务器端为开发者提供了一个清晰的流程。

再加上对Angular、jQuery、React、Vue和Svelte的支持,以及大量的插件,如图片预览和大小调整器,在考虑文件上传时,FilePond应该在你的选项列表中排在首位。

设置 FilePond 项目

让我们首先设置一个项目来保存示例代码。创建一个目录并将其称为/filepond。现在在命令行上进入该目录,并输入npm init 。接受所有的默认值。

现在用npm install express 安装 Express 服务器。接下来,创建一个index.html文件并把它放在项目根目录中。用清单1的内容更新这个新文件。

清单1.初始化的index.html

<html>
<head>
  <link href="https://unpkg.com/filepond/dist/filepond.css" rel="stylesheet" />
  <script src="https://unpkg.com/filepond/dist/filepond.js"></script>
</head>
<body>
  <input type="file">
</body>
<script>
  const inputElement = document.querySelector('input[type="file"]');
  const pond = FilePond.create( inputElement );
</script>
</html>

清单1一开始就从unpkg CDN中导入了FilePond的风格和代码。你也可以通过npm和构建工具来整合它,或者直接导入它。

标记只包括一个文件输入。最后,底部的脚本抓取一个对文件输入的引用,然后使用 FilePond API 创建一个新的 FilePond 实例,输入元素为FilePond.create( inputElement )

现在我们将添加一个脚本来运行该应用程序。修改package.json文件,包括清单2中的第7行。

清单 2.添加开发脚本

{
  "name": "filepond",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev": "nodemon server.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.17.1"
  }
}

通过在CLI中输入nodemon -v ,确保nodemon已经全局安装。如果没有找到它,用npm install -g nodemon

现在你可以通过在项目根部输入npm run dev 来运行该应用程序。

当应用程序运行时,你可以通过打开浏览器到http://localhost:43000/,访问简单的启动器页面。

迎接你的将是一个简单的文件输入组件。尽管FilePond还没有与后端相联系,但你可以通过点击浏览或将文件拖到FilePond组件上,继续从你的本地文件系统中选择一个文件。FilePond 会尽职尽责地将其排队。

处理文件上传

与后端互动的第一步是告诉 FilePond 它在哪里。FilePond 可以处理任何 URL。在我们的案例中,我们将使用来自同一域的相对路径。如果你使用一个到另一个域的绝对 URL,请记住CORS将发挥作用。

修改 index.html 中的脚本,包括清单 3 中的配置。

清单3.设置服务器 URL

<script>
  const inputElement = document.querySelector('input[type="file"]');
  const pond = FilePond.create( inputElement );
  pond.setOptions({
    server: "/upload"
  })
</script>

清单 3 告诉 FilePond 发送(通过 POST)文件位到相对 URL /upload。让我们在服务器上准备一个简单的处理程序来验证端点是否被击中。将清单 4 的代码添加到你的 index.js 文件中。

清单4.映射/upload POST

app.post("/upload", function(req, res){
  console.log("BEGIN /upload");
})

现在回到浏览器中,刷新页面。现在,当你上传文件时,你可以通过查看服务器日志和看到 "BEGIN /upload "输出来验证端点是否被访问。

保存临时文件

当你上传一个文件时,服务器首先会把文件暂时写在某个地方。服务器用一个唯一的ID来确认上传,当客户提交包含文件输入的表单时,它将包含这个唯一的ID。然后,服务器使用这个唯一的ID来定位临时文件,并将文件移到它的长期家园。

在服务器端,你可以采取许多不同的方法来支持这些要求,同时使用文件系统和数据库。

这个例子将使用Formidable库来处理 FilePond 发送的多部分 POST。Formidable是一个成熟的、有能力的库,而且它足够灵活,允许编写自定义流处理程序。例如,如果你想把文件保存到数据库中,你可以自己处理文件块并把它们流向数据存储。

在这个演示中,我们将简单地把临时文件写到磁盘上。开始安装Formidable。停止服务器(如果它正在运行)并输入npm install formidable 。现在你可以重新启动服务器。

转到index.js,在文件的开头插入这一行来导入库:

const formidable = require('formidable');

然后用清单5更新index.js。

清单5.接受临时文件

app.post("/upload", function(req, res){
  console.log("BEGIN /upload");
  const form = formidable({ multiples: false });

  form.parse(req, (err, fields, files) => {
    if (err) {
      next(err);
      return;
    }
    let theFile = files.filepond.path;
    console.log("theFile: " + theFile);

    res.writeHead(200, { 'Content-Type': 'text/plain' });
    res.end(theFile);
  });  
})

有了Formidable,接受文件就不难了。如果你现在通过Web界面上传文件,你会在日志中看到文件已经被写入默认的临时文件位置。以我的本地系统为例,它是C:\Users\mtyson\AppData\Local\Temp\。

你可以打开该文件并验证它是你发送的文件。

注意,应用程序使用文件路径发送了一个纯文本响应。这在现实世界中有些不安全,因为终端用户可以看到你的文件结构并收集关于系统的信息(比如我的文件路径显示它是一个Windows系统)。

对于生产使用来说,你需要一个间接层,即你保存文件并创建一个与文件路径相关的唯一ID。对于我们的目的,我们将只使用文件路径。

最后完成文件的上传

现在返回到客户端。我们将把上传者包裹在一个表单中并提交,并考虑把文件保存在哪里进行长期存储。由于表单只发送文件的路径(或唯一的ID),所以可以用JSON作为AJAX请求来轻松处理。我们将保持简单,在清单6中使用表单提交作为我们的例子。

清单6.上传者表单

<body>
  <form style="display:grid;" action="/save" method="POST">
    <input type="file">
    <button type="submit" onclick="">Save It</button>
  </form>
</body>

现在,当按钮被点击时,文件路径将被提交,默认标签为 "filepond"(这是可配置的)。在这种情况下,我们通过一个POST将信息发送到/save。

注意,如果你把文件输入设置为支持多个,FilePond将为你处理排队的多个文件。

为了处理提交,返回 index.js 并使用 Express urlencoded 中间件。

app.use(express.urlencoded({ extended: true }));

现在你已经准备好接收文件信息了。添加清单7中看到的处理程序。

清单7.接收保存信息

app.post("/save", function(req, res){
  console.log("BEGIN /save");
  console.log(`req: ${JSON.stringify(req.body)}`);
})

当清单7中的处理程序就位后,你应该看到日志来确认信息已经到达。日志将看起来像这样。

req: {"filepond":"C:\\Users\\mtyson\\AppData\\Local\\Temp\\upload_28331577a229fe48443275b2655a1abe"}

你现在可以自由地从磁盘上读取文件并做你想做的事。如清单8所示,可以用Node的内置fs模块从磁盘上读取文件。

清单8.从磁盘上读取临时文件

const fs = require('fs');
//...
let fileData = fs.readFileSync(req.body.filepond);

清单8创建了一个文件的缓冲区对象。你可以把它写到文件系统的另一个位置(同样使用fs模块),写到Amazon S3桶,或者写到MongoDB这样的数据库。

例如,在MongoDB中,你可以把缓冲区作为原样,像这样把它写到一个字段中。

require('mongodb').Binary(fileData)

这总结了上传和保存文件的整个周期。我们最后看一下图片预览器扩展。

在你的应用程序中添加图片预览器很简单,如清单9所示。

清单9.图像预览器插件

<head>
  ...
  <script src="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.js"></script>
  <link href="https://unpkg.com/filepond-plugin-image-preview/dist/filepond-plugin-image-preview.css" rel="stylesheet">
</head>
<body>
 ...
 FilePond.registerPlugin(FilePondPluginImagePreview);
 ...
</body>

现在,当你上传一个图像文件时,你会看到一个预览,如图1所示。

图1.图片预览器