Trung Quân
  • Node.js
  • ReactJS
    • Learn React Hooks
  • MERN Stack
  • Thuật Toán
  • Công Nghệ
    • Amazon AWS
    • Hosting – Domain
  • Về Tác Giả
  • Bản Quyền
Top Posts
Lộ trình học lập trình Web từ con...
Nhận diện, xác thực khuôn mặt với ReactJS...
Tạo hiệu ứng thẻ bài Magic với HTML...
NodeJS viết API gửi Email với OAuth2 và...
Tạo hiệu ứng Parallax đơn giản chỉ với...
Git – GitHub • Học Git thực tế...
Tạo một trang GitHub Profile phiên bản vũ...
Cài đặt iTerm2, Oh My Zsh, Zsh-autosuggestions và...
Cài đặt NVM, NodeJS và GIT trên MacOS...
Thuật toán Tìm phần tử bị lặp đầu...

Trung Quân

  • Node.js
  • ReactJS
    • Learn React Hooks
  • MERN Stack
  • Thuật Toán
  • Công Nghệ
    • Amazon AWS
    • Hosting – Domain
  • Về Tác Giả
  • Bản Quyền
Node.js

Upload multiple files trong NodeJS

by trungquandev August 18, 2019
written by trungquandev August 18, 2019
nodejs-upload-multiple-files-trungquandev

Xin chào tất cả các bạn, mình là Quân, tiếp tục ở bài trước, mình đã hướng dẫn các bạn upload file trong Nodejs nhưng mới chỉ là upload single mỗi file một lần, nên hôm nay chúng ta sẽ cùng nhau đi xử lý xem việc upload nhiều file cùng một lúc nó như thế nào nhé.

“Bài này nằm trong loạt bài Lập Trình Nodejs từ cơ bản đến nâng cao trên trang blog chính thức trungquandev.com“

Những nội dung có trong bài:

  1. Tản mạn phân tích bài toán
  2. Dán mắt vào màn hình để code…
  3. Demo ứng dụng upload multiple files.
  4. Full source code trên github.

1. Tản mạn phân tích bài toán

Như ở bài trước, mình đã hướng dẫn cho các bạn xử lý upload file trong NodeJS bằng 2 module là Formidable và Multer. Nhưng nội dung ở bài đó mới chỉ dừng lại ở việc upload file đơn lẻ, có nghĩa là upload mỗi lần mỗi file.

Nên trong bài viết ngày hôm nay, chúng ta sẽ cùng nhau đi xử lý việc upload nhiều file trong NodeJS nhé.

Hôm nay để không lan man và để “focus on the point” thì mình sẽ chỉ hướng dẫn cho các bạn làm việc với thằng Multer thôi nhé, đây là module mà mình khá thích vì tính dễ dàng sử dụng của nó. Bạn nào chưa rõ thì có thể xem lại bài upload file trong nodejs hôm trước của mình, mình có phân tích khá rõ về module này trước khi code rồi nha.

Ok, tản mạn đủ rồi, chúng ta bắt đầu đi vào code nhé.

2. Dán mắt vào màn hình để code

Đầu tiên là cấu trúc thư mục, phần này rất quan trọng, mình sẽ làm rất rõ ràng, chia nhỏ các thành phần code nên các bạn chịu khó học nhé, sẽ rất bổ ích cho những bạn mới học đấy:

src

controllers

homeController.js

multipleUploadController.js

middleware

multipleUploadMiddleware.js

routes

web.js

views

master.html

uploadResults

server.js

package.json

Việc khởi tạo ứng dụng nodejs thì mình không làm lại, các bạn có thể xem cách làm ở bài viết trước của mình tại link bên dưới đây: (Ngoài lề: Mấy bạn admin của mấy trang TopDev, TechBlog…vv gì đấy đã đi copy bài không phải của các bạn thì hãy tôn trọng người viết, đừng có xóa đoạn quan trọng này cũng như tự ý xóa linh tinh các câu thoại của mình trong bài viết này, lần này nếu mình phát hiện ra nữa thì chắc chắn sẽ ăn report DMCA nhé.)
https://trungquandev.com/series-lap-trinh-nodejs/

Trước khi đi vào code, chúng ta sẽ cần phải cài 2 module cho bài hôm nay đó là:
express và multer

npm install --save express multer

Chúng ta bắt đầu code lần lượt như sau:

Đầu tiên là file views/master.html

File này các bạn cần lưu ý một vài điểm:

  • Thứ nhất là cái form upload <form action="/multiple-upload"method="POST"enctype="multipart/form-data">
  • Thứ hai là thẻ <input type="file"name="many-files" multipleid="input-many-files"class="form-control-file border">
  • Còn lại có cái đoạn script phía dưới cùng mình viết để khi chọn ảnh xong nó sẽ preview lên trình duyệt cho chúng ta xem trước, mình không giải thích trong bài vì sợ lan man, bạn nào muốn hiểu rõ phần này có thể comment dưới bài viết, mình sẽ giải đáp sau nhé.
<!--
* Created by trungquandev.com's author on 17/08/2019.
*/
// views/master.html
-->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <link rel="shortcut icon" href="https://trungquandev.com/wp-content/uploads/2016/11/LOGO.png" />
    <title>Node.js multiple upload files</title>

    <!-- Get bootstrap from CDN-->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">

    <style>
        div.preview-images>img {
            width: 30%;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="row">
            <div class="col-sm-8">
                <br>
                <h4>
                    Node.js multiple upload files - <a href="https://trungquandev.com" target="blank">trungquandev.com</a>
                </h4>
                <div class=""></div>
                <form action="/multiple-upload" method="POST" enctype="multipart/form-data">
                    <div class="form-group">
                        <label for="example-input-file"> </label>
                        <input type="file" name="many-files" multiple id="input-many-files" class="form-control-file border">
                    </div>
                    <button type="submit" class="btn btn-primary">Submit</button>
                </form>
            </div>
        </div>
        <hr>
        <div class="row">
            <div class="col-sm-12">
                <div class="preview-images"></div>
            </div>
        </div>
    </div>

    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js"></script>
    <script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
    <script>
        $(document).ready(function() {
            // Multiple images preview in browser - trungquandev.com
            let imagesPreview = function(input, placeToInsertImagePreview) {
                if (input.files) {
                    let filesAmount = input.files.length;
                    for (i = 0; i < filesAmount; i++) {
                        let reader = new FileReader();
                        reader.onload = function(event) {
                            $($.parseHTML("<img>")).attr("src", event.target.result).appendTo(placeToInsertImagePreview);
                        }
                        reader.readAsDataURL(input.files[i]);
                    }
                }
            };

            $("#input-many-files").on("change", function() {
                imagesPreview(this, "div.preview-images");
            });
        });
    </script>
</body>
</html>

Tiếp theo tới file middleware/multipleUploadMiddleware.js

File này gói gọn lại chức năng upload files và export ra để bên controller lát nữa mình sử dụng
Trong file này thì các bạn để ý cho mình là ngoài multer ra thì mình có dùng thêm util để convert lại thằng multer cho nó khả dụng với Promise, và thằng path để lấy đường dẫn gốc của file hiện tại.

/**
 * Created by trungquandev.com's author on 17/08/2019.
 * multipleUploadMiddleware.js
 */
const util = require("util");
const path = require("path");
const multer = require("multer");

// Khởi tạo biến cấu hình cho việc lưu trữ file upload
let storage = multer.diskStorage({
  // Định nghĩa nơi file upload sẽ được lưu lại
  destination: (req, file, callback) => {
    callback(null, path.join(`${__dirname}/../../uploadResults`));
  },
  filename: (req, file, callback) => {
    // ở đây các bạn có thể làm bất kỳ điều gì với cái file nhé.
    // Mình ví dụ chỉ cho phép tải lên các loại ảnh png & jpg
    let math = ["image/png", "image/jpeg"];
    if (math.indexOf(file.mimetype) === -1) {
      let errorMess = `The file <strong>${file.originalname}</strong> is invalid. Only allowed to upload image jpeg or png.`;
      return callback(errorMess, null);
    }

    // Tên của file thì mình nối thêm một cái nhãn thời gian để tránh bị trùng tên file.
    let filename = `${Date.now()}-trungquandev-${file.originalname}`;
    callback(null, filename);
  }
});

// Khởi tạo middleware uploadManyFiles với cấu hình như ở trên,
// Bên trong hàm .array() truyền vào name của thẻ input, ở đây mình đặt là "many-files", và tham số thứ hai là giới hạn số file được phép upload mỗi lần, mình sẽ để là 17 (con số mà mình yêu thích). Các bạn thích để bao nhiêu cũng được.
let uploadManyFiles = multer({storage: storage}).array("many-files", 17);

// Mục đích của util.promisify() là để bên controller có thể dùng async-await để gọi tới middleware này
let multipleUploadMiddleware = util.promisify(uploadManyFiles);

module.exports = multipleUploadMiddleware;

File controller/homeController.js

File này không có gì khó hiểu cả, trong nó có một function trả về cái màn hình cho chúng ta chọn file để upload, chính là trả về file master.html ở trên kia:

/**
 * Created by trungquandev.com's author on 17/08/2019.
 * homeController.js
 */

const path = require("path");

let getHome = (req, res) => {
  return res.sendFile(path.join(`${__dirname}/../views/master.html`));
};

module.exports = {
  getHome: getHome
};

File controller/multipleUploadController.js

Ở controller này, chúng ta sẽ import cái multipleUploadMiddleware vừa viết lúc nãy và sử dụng nó với async-await, nếu có lỗi thì trả về thông báo lỗi tương ứng, ngược lại nếu thành công thì trả về dòng thông báo “Your files has been uploaded.”

/**
 * Created by trungquandev.com's author on 17/08/2019.
 * multipleUploadController.js
 */
const multipleUploadMiddleware = require("../middleware/multipleUploadMiddleware");

let debug = console.log.bind(console);

let multipleUpload = async (req, res) => {
  try {
    // thực hiện upload
    await multipleUploadMiddleware(req, res);

    // Nếu upload thành công, không lỗi thì tất cả các file của bạn sẽ được lưu trong biến req.files
    debug(req.files);

    // Mình kiểm tra thêm một bước nữa, nếu như không có file nào được gửi lên thì trả về thông báo cho client
    if (req.files.length <= 0) {
      return res.send(`You must select at least 1 file or more.`);
    }

    // trả về cho người dùng cái thông báo đơn giản.
    return res.send(`Your files has been uploaded.`);
  } catch (error) {
    // Nếu có lỗi thì debug lỗi xem là gì ở đây
    debug(error);

    // Bắt luôn lỗi vượt quá số lượng file cho phép tải lên trong 1 lần
    if (error.code === "LIMIT_UNEXPECTED_FILE") {
      return res.send(`Exceeds the number of files allowed to upload.`);
    }

    return res.send(`Error when trying upload many files: ${error}}`);
  }
};

module.exports = {
  multipleUpload: multipleUpload
};

File routes/web.js

File này là nơi chúng ta cấu hình routers cho ứng dụng, sẽ có 2 route chính, một là để gọi ra màn hình chọn file upload, có method là GET, route còn lại là gọi đến controller upload file ở ngay phía trên, method là POST.

/**
 * Created by trungquandev.com's author on 17/08/2019.
 * routes/web.js
 */
const express = require("express");
const router = express.Router();
const homeController = require("../controllers/homeController");
const multipleUploadController = require("../controllers/multipleUploadController");

let initRoutes = (app) => {
  // Gọi ra trang home cho việc upload
  router.get("/", homeController.getHome);
  
  // Upload nhiều file với phương thức post
  router.post("/multiple-upload", multipleUploadController.multipleUpload);

  return app.use("/", router);
};

module.exports = initRoutes;

File server.js

Và cuối cùng, “last but not least”, file server.js của chúng ta, sử dụng để chạy ứng dụng nodejs:

/**
 * Created by trungquandev.com's author on 17/08/2019.
 * server.js
 */
const express = require("express");
const app = express();
const initRoutes = require("./routes/web");

// Cho phép lý dữ liệu từ form method POST
app.use(express.urlencoded({extended: true}));

// Khởi tạo các routes cho ứng dụng
initRoutes(app);

// chọn một port mà bạn muốn và sử dụng để chạy ứng dụng tại local
let port = 8017;
app.listen(port, () => {
  console.log(`Hello trungquandev.com, I'm running at localhost:${port}/`);
});

3. Demo ứng dụng upload multiple files

Sau khi đã xử lý xong tất cả các file ở trên, chúng ta sẽ chạy ứng dụng bằng lệnh:
node src/server.js

Kết quả đầu tiên sẽ hiện lên màn hình cho chúng ta chọn files:

Mình sẽ chọn upload 3 file ảnh như hình bên dưới:

Nếu upload thành công thì trả về cho phía client:

Ngoài ra thì các bạn có thể vào phần code, mình có log ra file sau khi upload và cả 3 file đều đã nằm trong thư mục uploadResults:

Một số lỗi mà mình bắt ra sau đây đó là không chọn file nào mà nhấn submit, vượt quá số lượng file cho phép upload và upload kiểu file không hợp lệ:

4. Full source code trên github

Vậy là bài hôm nay chúng ta đã cùng nhau hoàn thiện về ý tưởng và cách triển khai cho việc upload nhiều file trong Nodejs rồi.

Mình có để full source code của bài hôm nay ở repo này cho các bạn tham khảo nhé, nếu thấy bài viết bổ ích, hãy ủng hộ bằng cách cho mình 1 star trên repo này để mình có động lực tiếp tục viết những bài viết chất lượng nha, cảm ơn các bạn.
https://github.com/trungquandev/nodejs-upload-multiple-files


Cảm ơn các bạn đã dành thời gian đọc bài viết.

Xin chào và hẹn gặp lại các bạn ở những bài viết tiếp theo.

Best Regards – Trung Quân – Green Cat


Tham khảo kiến thức:

https://www.npmjs.com/package/multer

“Thanks for awesome knowledges.”

Khóa học lập trình làm việc thực tế:

Nếu các bạn thấy bài viết của mình có ích thì hãy ủng hộ mình bằng cách tham khảo bài viết giới thiệu khóa học lập trình MERN Stack Miễn Phí cực kỳ chất lượng và chính chủ dưới đây của mình nhé, cảm ơn các bạn ^^
KHOÁ HỌC LẬP TRÌNH MERN STACK 100% DỰ ÁN THỰC TẾ và CHẤT LƯỢNG
mern-stack-course-trungquandev
multernodejstrungquandevupload-fileupload-multiple-files
2 comments
0
FacebookTwitterGoogle +Pinterest
trungquandev

previous post
Node.js lắng nghe, quan sát những thay đổi của File, Folder
next post
Hiểu sâu về JWT – JSON Web Tokens

Related Posts

Series lập trình Node.js

April 8, 2018

NodeJS viết API gửi Email với OAuth2 và...

May 17, 2022

Hướng dẫn Loop through Object trong Javascript ES6

December 25, 2019

Quản lý (upgrade/downgrade) phiên bản NodeJS dễ dàng...

August 17, 2020

Một cái nhìn tổng quan nhất về Node.js

April 8, 2018

Cấu hình Babel cho một dự án Node.JS...

April 29, 2021

Node.js – Cài đặt môi trường phát triển...

May 23, 2018

Gửi nhận email trong NodeJS cực kỳ đơn...

February 20, 2020

Xây dựng ứng dụng “động vật ẩn danh”...

January 15, 2018

Upload file trong Node.js?

March 12, 2019

Bát Chánh Đạo

batchanhdao-trungquandev

About Me

About Me

Trung Quân

Software Engineer at Pod Foods

Academy Of Cryptography Techniques

"I am a dog and cat lover, love green, love to read books, write blog and oil painting ..."

Read my CV → https://cv.trungquandev.com/

My Maxim Live

A bit of fragrance clings to the hand that gives flowers!

For Vietnamese young generation

Đừng bao giờ làm người khổng lồ trong tư tưởng nhưng chỉ là thằng lùn trong hành động.

Keep in touch

Facebook Instagram Linkedin Youtube Email Github

Fanpage Facebook

Facebook

Học lập trình “MERN Stack Cơ Bản” qua ứng dụng thực tế

mern-stack-trello-app-trungquandev


  Khóa học lập trình MERN Stack (NodeJS, ReactJS, ExpressJS, MongoDB) cực kỳ chất lượng và Miễn Phí do chính mình hướng dẫn nhé:
  MERN Stack - xây dựng ứng dụng quản lý công việc dạng Kanban tương tự Trello.

Học lập trình “MERN Stack Nâng Cao” qua ứng dụng thực tế

mern-stack-advanced-trello-app-trungquandev


  * Học lập trình MERN Stack Nâng Cao (NodeJS, ReactJS, ExpressJS, MongoDB). Đây là một khóa học mà mình đã làm cực kỳ tâm huyết, với phong cách dạy lập trình làm dự án thực tế, chuyên nghiệp. Để các bạn có một hành trang kiến thức vững chắc cho hành trình làm lập trình viên trong tương lai nhé.
  Lập Trình MERN Stack Nâng Cao - Học Thực Tế Để Đi Làm

YouTube: Trungquandev Official

youtube-channel-trungquandev-official


  - Các bạn tham khảo kênh YouTube chính thức của mình và ủng hộ mình bằng cách tặng mình một lượt Đăng Ký Kênh nha.
Cảm ơn các bạn ^^

  YouTube: TRUNGQUANDEV OFFICIAL

© Copyright

Bản quyền:
  © DMCA (Digital Millennium Copyright Act)


DMCA.com Protection Status

License

Giấy phép nội dung:
  Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 Quốc tế.


Giấy phép Creative Commons

Other links

Portfolio của mình:
  https://cv.trungquandev.com

Lập trình cuộc sống:
  https://laptrinhcuocsong.com

Nhiều bài viết hay về javascript:
  https://codetheworld.io

  • Facebook
  • Youtube
  • GitHub
  • Linkedin
  • Instagram

@2022 - trungquandev.com. Since 2016 - All Right Reserved. Developed by Trung Quân Dev