Node.js - Upload Files

Trong nhiều ứng dụng web, người dùng từ máy khách cần phải tải lên tệp (chẳng hạn như người dùng tải lên hình ảnh và video với các ứng dụng Facebook hoặc Instagram) lên máy chủ. Có một số mô-đun mã nguồn mở có sẵn trên kho NPM, với các mô-đun này, tính năng tải lên tệp có thể được kích hoạt trong ứng dụng Node.js. Mô-đun formidable cung cấp một API tiện lợi để xử lý việc tải lên tệp. Mô-đun formidable có thể được nhập vào một mô-đun Node.js cốt lõi cùng với mô-đun http tích hợp sẵn, cũng như ứng dụng Express.

Formidable

Mô-đun Formidable là một trình phân tích đa phần nhanh và theo dòng, có khả năng tự động ghi các tệp tải lên vào đĩa. Nó có mức tiêu thụ bộ nhớ thấp, với cơ chế xử lý lỗi hiệu quả.

Bước đầu tiên, hãy cài đặt mô-đun formidable bằng lệnh sau −

npm install formidable

Trong chương này, việc sử dụng ví dụ về mô-đun Formidable trong một ứng dụng node.js bao gồm mô-đun http và trong một ứng dụng ExpressJs được trình bày dưới đây −

with Node.js http module

Ví dụ dưới đây gọi hàm createServer() để khởi động máy chủ Node.JS và hiển thị một biểu mẫu HTML đa phần để người dùng chọn tệp cần tải lên.

Khi tệp được gửi, dữ liệu biểu mẫu sẽ được phân tích và tệp đã tải lên sẽ được sao chép vào vị trí mặc định trên đĩa.

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 http://localhost:5000/ ...');
});

Khi ứng dụng được chạy, trình duyệt hiển thị biểu mẫu sau để chọn một tệp để tải lên.

Nodejs http Module

Sau khi hoàn tất thao tác tải lên, trình duyệt sẽ hiển thị kết quả sau −

{
  "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"
         }
      ]
   }
}

with Express.js

Cách sử dụng đơn giản nhất của mô-đun formidable trong mã Express.JS như sau −

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 http://localhost:5000 ...');
});

Bạn cũng có thể cài đặt và sử dụng module body-parser để phân tích dữ liệu biểu mẫu HTML đa phần trong quá trình tải lên.

Multer

Một mô-đun NPM hữu ích khác có khả năng xử lý việc tải lên tệp được gọi là Multer. Người dùng có thể tải lên một hoặc nhiều tệp cùng một lúc.

Để cài đặt, hãy sử dụng lệnh sau −

npm install multer

Ở đầu ứng dụng Express, hãy bao gồm multer và khai báo đối tượng Multer.

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

Giả sử rằng bạn có một tuyến đường để xử lý yêu cầu GET và hiển thị một biểu mẫu HTML đa phần tử mà gửi biểu mẫu đến tuyến đường /upload, hãy thêm chức năng sau để xử lý yêu cầu POST −

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

Để lưu trữ tệp đã tải lên tại một vị trí cụ thể thay vì vị trí mặc định của tệp tạm thời, hãy cấu hình vị trí Multer như sau −

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 })