• Node.js Video Tutorials

Node.js - 上传文件



在许多 Web 应用程序中,客户端机器上的用户需要将文件(例如用户使用 Facebook 或 Instagram 应用程序上传图像和视频)上传到服务器。NPM 注册表上提供了许多开源模块,可以使用这些模块在 Node.js 应用程序中启用上传文件的功能。formidable 模块提供了一个方便的 API 来处理文件上传。formidable 模块可以导入到核心 Node.js 模块中,以及内置的 http 模块和 Express 应用程序中。

Formidable

Formidable 模块是一个快速且流式处理的多部分解析器,能够自动将文件上传写入磁盘。它占用内存少,并且具有高效的错误处理机制。

第一步,使用以下命令安装 formidable 模块:

npm install formidable

在本节中,下面显示了在包含 http 模块的 Node.js 应用程序和 ExpressJs 应用程序中使用 Formidable 模块的示例用法:

使用 Node.js http 模块

以下示例调用 createServer() 函数启动 Node.JS 服务器,并呈现一个多部分 HTML 表单,供用户选择要上传的文件。

提交文件后,表单数据将被解析,并且上传的文件将复制到磁盘上的默认位置。

var http = require('http');
var formidable = require('formidable');

var errors = formidable.formidableErrors;

const server = http.createServer(async (req, res) => {
   if (req.url === '/api/upload' && req.method.toLowerCase() === 'post') {
      // parse a file upload
      const form = new formidable.IncomingForm();
      let fields;
      let files;
      try {
         [fields, files] = await form.parse(req);
      } catch (err) {

         res.writeHead(err.httpCode || 400, { 'Content-Type': 'text/plain' });
         res.end(String(err));
         return;
      }
      res.writeHead(200, { 'Content-Type': 'application/json' });
      res.end(JSON.stringify({ fields, files }, null, 2));
      return;
   }

   // show a file upload form
   res.writeHead(200, { 'Content-Type': 'text/html' });
   res.end(`
      <h2>With Node.js <code>"http"</code> module</h2>
      <form action="/api/upload" enctype="multipart/form-data" method="post">
      <div>Text field title: <input type="text" name="title" /></div>
      <div>File: <input type="file" name="multipleFiles" multiple="multiple" /></div>
      <input type="submit" value="Upload" />
      </form>
   `);
});
server.listen(5000, () => {
   console.log('Server listening on https://127.0.0.1:5000/ ...');
});

运行应用程序后,浏览器将显示以下表单以选择要上传的文件。

Nodejs http Module

上传操作成功后,浏览器将显示以下结果:

{
  "fields": {
      "title": [
         "test"
      ]
   },
   "files": {
      "multipleFiles": [
         {
            "size": 4203211,
            "filepath": "C:\\Users\\user\\AppData\\Local\\Temp\\930f2f754006b790729e0d200",
            "newFilename": "930f2f754006b790729e0d200",
            "mimetype": "image/png",
            "mtime": "2023-12-24T08:04:09.856Z",
            "originalFilename": "1.png"
         }
      ]
   }
}

使用 Express.js

在 Express.JS 代码中使用 formidable 模块的最简单用法如下:

import express from 'express';
import formidable from 'formidable';

const app = express();

app.get('/', (req, res) => {
   res.send(`
      <h2>With <code>"express"</code> npm package</h2>
      <form action="/api/upload" enctype="multipart/form-data" method="post">
      <div>Text field title: <input type="text" name="title" /></div>
      <div>File: <input type="file" name="someExpressFiles" multiple="multiple" /></div>
      <input type="submit" value="Upload" />
      </form>
   `);
});
app.post('/api/upload', (req, res, next) => {
   const form = formidable({});

   form.parse(req, (err, fields, files) => {
      if (err) {
         next(err);
         return;
      }
      res.json({ fields, files });
   });
});

app.listen(5000, () => {
   console.log('Server listening on https://127.0.0.1:5000 ...');
});

您还可以安装并使用 body-parser 模块来解析上传过程中多部分 HTML 表单数据。

Multer

另一个能够处理文件上传的有用 NPM 模块称为 Multer。用户可以一次上传一个或多个文件。

要安装,请使用以下命令:

npm install multer

在 Express 应用程序的开头,包含 Multer 并声明 Multer 对象。

const multer  = require('multer')
const upload = multer({ dest: 'uploads/' })

假设您有一个路由来处理 GET 请求并显示一个将表单发布到 /upload 路由的多部分 HTML 表单,请添加以下函数来处理 POST 请求:

app.post("/upload", upload.single("myFile"), (req, res) => {
   console.log("Body: ", req.body);
   console.log("File: ", req.file);
   res.send("File successfully uploaded.");
});

要将上传的文件存储在指定位置而不是临时文件的默认位置,请配置 Multer 位置如下:

var storage = multer.diskStorage({   
   destination: function(req, file, cb) { 
      // destination is used to specify the path of the directory in which the files have to be stored
      cb(null, './uploads');    
   }, 
   filename: function (req, file, cb) { 
      // It is the filename that is given to the saved file.
      cb(null , file.originalname);   
   }
});

// Configure storage engine instead of dest object.
const upload = multer({ storage: storage })
广告