Ví dụ upload files trong Nodejs

Ví dụ upload files trong Nodejs là vấn đề được nhiều lập trình viên quan tâm, bởi những kiến thức trên trường lớp là không đủ, vì vậy bài Ví dụ upload files trong Nodejs sẽ chia sẻ tới bạn nhiều thông tin hữu ích

Mọi người vẫn hỏi tôi về việc học lập trình nói chung và NodeJS nói riêng có cần năng khiếu hay quá khó để tiếp cận hay không. Thì tôi có thể trả lời rằng, học lập trình cũng như việc bạn học tiếng Anh hay bất kỳ một ngôn ngữ khác, bởi lập trình...là ngôn ngữ của máy tính, để máy tính đọc và máy tính thực hiện theo yêu cầu của mình, bạn thích là học được.

Trong bài viết này chúng ta sẽ cùng nhau xây dựng một trang web upload file sử dụng NodeJS, bài này mình sẽ cố gắng đi từng bước và giải thích kĩ từng đoạn code làm sao cho dễ hiểu nhất. Mình sẽ sử dụng kết hợp giữa các module như formidable đùng để parse form, module http giúp khởi tạo HTTP Web Server, module fs để xử lý file.

1. Module formidable

Có rất nhiều module hữu ích cho việc upload một file sử dụng Nodejs, mình sẽ sử dụng module formidable. Để cài đặt module này bạn cần mở terminal và gõ dòng lệnh:

  npm i --save formidable 

Sau khi cài đặt module xong bạn cần phải include nó vào chương trình:

  const formidable = require('formidable') 

Mình chọn module formidable bởi nó là một module khá phổ biến mà có một vài điểm nổi bật như:

  • Tốc độ khá nhanh (khoảng từ 900-2500MB/s) và parse dữ liệu ra nhiều luồng (sử dụng streams trong nodejs)
  • Tự động ghi file vào ổ đĩa ( tại thời điểm mà mình viết bài này thì nó chưa hỗ trợ, bạn cần cùng kết hợp module fs để ghi file)
  • Plugin API cho phép người dùng chỉnh cách thức parse và các plugin hỗ trợ.
  • Chiếm ít bộ nhớ
  • Dễ dàng bắt lỗi
  • Nhiều phương thức cho việc test

2. Xây dựng trang upload file sử dụng Nodejs

Mình sẽ chia cấu trúc thư mục của dự án thành 3 phần như sau:

  • viewUploadForm.html : đây là file dùng để chứa giao diện trang web
  • index.js: file chứa các đoạn code xử lý của server
  • /uploads : thư mục chứa các file

Xây dựng giao diện trang upload

Mình sẽ dùng framework Bootstrap 4 để xây dựng trang giao diện một cách nhanh hơn. File viewUploadForm.html dẽ có nội dung như sau:

<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload file using NodeJS</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css">
</head>
<body>
    <div class="container">
        <div class="row" >
            <div class="col-md-12">
                <div class="card"  style="margin-top: 5%; padding: 5%;">
                    <h3 style="text-align: center;">Upload file using nodejs - hoidapcode.com</h3><hr>
                    <form action="/upload" method="POST" enctype="multipart/form-data">
                        <div class="form-group">
                            <input type="file" name="files" class="form-control-file border">
                        </div>
                        
                        <button class="btn btn-primary btn-block">Upload File</button>
                    </form>
                </div>
                 
            </div>
        </div>
    </div>
</body>
</html> 

Ở đây mình sẽ tạo một form upload có action="/upload" mà method là POST, attribute enctype="multipart/form-data" chỉ định form sẽ đươc encode.

Xây dựng HTTP Web Server

Bạn cần xây dựng HTTP Web Server để xử lý các yêu cầu từ người dùng, cụ thể trong dự án này là upload file. Để khởi tạo bạn cần phải sử dụng module HTTP có trong Nodejs. Nếu bạn không biết cách khởi tạo HTTP Web Server bạn hãy đọc bài viết cách khởi tạo HTTP Web Server trong NodeJS mà mình đã viết trong seri này trước đó.

Trong file index.js ta tiến hành dùng hàm http.createServer() để khởi tạo server:

const http = require('http');
const formidable = require('formidable');
const fs = require('fs');
 
//Sử dujgn module fs để đọc nội dung file viewUploadForm
const viewFormUpload = fs.readFileSync('./viewUploadForm.html')
 
//Khởi tạo server
http.createServer(function (req, res) {
  //Bắt yêu cầu resquest gửi đến url /upload có method là POST
  if (req.url == '/upload' && req.method == 'POST') {
    
  } else {
    //Hiển thị ra form upload file
    res.writeHead(200, {'Content-Type': 'text/html'});
    return res.end(viewFormUpload);
  }
}).listen(6969); //Sử dụng port 6969 

Server sẽ lắng nghe ở port 6969, và trả về form upload. Vì giao diện của trang web nằm trong file viewFormUpload.html nên để lấy nội dung file đó mình phải dùng module fs của NodeJS để đọc.

Xử lý yêu cầu upload file từ người dùng

Khi upload file người dùng sẽ được gửi một request mới method là POST, việc cần làm bây giờ dùng module formdable để parse form. Trong phần kiểm tra điều kiện người dùng đã upload file đến server bạn sẽ xử lý upload file như sau:

//Khởi tạo API formidable
    const form = new formidable.IncomingForm();
    //Tiến hành parse form
    form.parse(req, function (err, fields, files) {
      //Lấy đượng dẫn tạm thời của  file khi upload
      let oldPath = files.files.path
      //Đường dẫn mới khi upload 
      let newPath = __dirname + '/uploads/' + files.files.name
      //Tiến hành rename file tạm thời thành đường dẫn file mới
      fs.rename(oldPath, newPath, (err) => {
         //Trả ra lõi nếu gặp
         if (err) return res.end(err)
 
         //Trả về kết quả thành công
         return res.end('<h1 style="color: green;">Upload success !</h1>')
      })
    }) 

Trước tiên bạn phải khởi tạo API IncomingForm() để formidable biết rằng có form submit, sau đó dùng hàm form.parse() để parse request của clients gửi về lúc này hàm sẽ trả về một callback chứa các giá trị khi form đã được parse. Việc bạn cần làm bây giờ là rename file bằng module fs.

Module formidable còn cho phép bạn thêm một số options, bạn có thể truyền 1 objects chứ các tinh chỉnh vào hàm:

 const options = {
      //Options object
}
const form = new formidable.IncomingForm(options); 

Chúng ta có thể tinh chỉnh một vài giá trị như :

  • options.encoding {string} - Mặc định 'utf-8', tinh chỉnh kiểu encode ở các trường ở form.
  • options.uploadDir {string} - Đường dẫn mặc định khi upload file, bạn có thể chỉnh sửa sau đó sử dụng fs.rename(). Mặc định sẽ là os.tmpdir()
  • options.keepExtensions {boolean} - mặc định là false, có giữ phần
  • options.maxFileSize {number} - mặc định 200 * 1024KB = 200MB, giới file tối đa uploads
  • options.maxFields {number} - mặc 1000; giới hạn các trường để parse, đặt 0 đẻ không giới hạn.
  • options.maxFieldsSize {number} - default 20 * 1024 * 1024 (20mb);giới hạn bộ nhớ được dùng để parse các trường (trừ trường files)
  • options.hash {boolean} - mặc định false; kiểm tra tổng thể được tính cho các tệp đến, đặt thuật toán này thành một số thuật toán băm, xem crypto.createHash để biết các thuật toán có sẵn
  • options.multiples {boolean} - mặc định false; khi bạn gọi phương thức .parse, đối số tệp (của callback) sẽ chứa các mảng tệp cho các đầu vào gửi nhiều tệp bằng cách sử dụng nhiều thuộc tính HTML5. Ngoài ra, đối số trường sẽ chứa các mảng giá trị cho các trường có tên kết thúc bằng '[]'.

Cuối cùng file index.js khi hoàn thiện sẽ như sau:

 const http = require('http');
const formidable = require('formidable');
const fs = require('fs');
 
//Sử dụng module fs để đọc nội dung file viewUploadForm
const viewFormUpload = fs.readFileSync('./viewUploadForm.html')
 
//Khởi tạo server
http.createServer(function (req, res) {
  //Bắt yêu cầu resquest gửi đến url /upload có method là POST
  if (req.url == '/upload' && req.method == 'POST') {
    //Khởi tạo đối tượng formidable
    const option = {
       
    }
    const form = new formidable.IncomingForm();
    //Tiến hành parse form
    form.parse(req, function (err, fields, files) {
      //Lấy đượng dẫn tạm thời của  file khi upload
      let oldPath = files.files.path
      //Đường dẫn mới khi upload 
      let newPath = __dirname + '/uploads/' + files.files.name
      //Tiến hành rename file tạm thời thành đường dẫn file mới
      fs.rename(oldPath, newPath, (err) => {
         //Trả ra lõi nếu gặp
         if (err) return res.end(err)
 
         //Trả về kết quả thành công
         return res.end('<h1 style="color: green;">Upload success !</h1>')
      })
    })
  } else {
    //Hiển thị ra form upload file
    res.writeHead(200, {'Content-Type': 'text/html'});
    return res.end(viewFormUpload);
  }
}).listen(6969); //Sử dụng port 6969

Trên đây là những kiến thức cơ bản về xử lý upload file trong Nodejs, thường thì khi xử lý upload file người ta dùng module Multer để hỗ trợ upload và module Express để khởi tạo server. Vì đây là bài viết nằm tronng phần NodeJS cơ bản nên mình sẽ đề cập đến việc upload file bằng cách kết hợp giữa 2 module Multer và Express trong phần về Express framework. Mong bài viết này có thể giúp ích cho bạn cho việc lập trình với Nodejs, cảm ơn bạn đã quan tâm bài viết này.

Hy vọng với bài viết về Ví dụ upload files trong Nodejs đã giải đáp giúp bạn phần nào về kiến thức lập trình NodeJS. Như tôi đã nói, ngôn ngữ lập trình không quan trọng bằng tư duy giải thuật, tư duy logic để giải quyết vấn đề.

Với những năm trước đây, lập trình viên là một cái nghề khó và kén chọn người học, đồng nghĩa với việc thu nhập hàng tháng của các lập trình viên luôn cao. Còn những năm gần đây, thì lập trình là môn học phổ thông, và ai cũng nên học một ngôn ngữ lập trình nào đó.

Nếu bạn còn bất kỳ câu hỏi nào trong việc học lập trình online, hãy gửi yêu cầu cho tôi qua email hoidapcode.com@gmail.com hoặc để lại comment bên dưới, tôi sẽ giải đáp trong vòng 24 giờ!

Blog hoidapcode.com là blog được tổng hợp tự động các bài học, thông tin về lập trình trên mạng internet. Nếu bạn có ý kiến hoặc đóng góp về bài viết này, hãy liên hệ với tôi!