Uploading files Cloudinary using Multer and ExpressJS

Uploading files Cloudinary using Multer. Sau bài viết "upload files using multer expressJs" và tôi đã hứa là sẽ show cho các bạn một ví dụ về upload images lên cloudinary sử dụng multer. Cloudinary là gì? Tại sao tôi lại chọn hosting này? Và câu trả lời sẽ có trong bài viết này. Trước khi tiếp tục hành trình upload file lên Cloudinary thì tôi muốn các bạn nên xem bài viết trước đó là upload files với Multer. Lúc đó bạn sẽ hiểu hơn và chính tôi cũng đỡ phải giải thích lại về cách sử dụng Multer. Ok bắt đầu thôi. 

Cloudinary là gì? What's Cloudinary? 

Cloudinary là một giải pháp quản lý và xử lý những hình ảnh từ a tới z cho website và app mobile của bạn. Cloudinary bao gồm mọi thứ, từ tải lên hình ảnh, lưu trữ, thao tác, tối ưu hóa để giúp trang web hay ứng dụng load mượt. Chúng ta có thể upload trực tiếp trên trang web cloudinary. Nhưng bên cạnh đó cloudinary api cũng hỗ trợ trong việc upload files trong nodejs. Và đặc biệt hơn nữa, chính là chúng ta có thể drop image hay compress image thông qua api cloudinary.

Tại sao chọn Cloudnary để upload files.

Có thể bạn đã từng rơi vào tình huống đó là khi bạn upload file lên local server và chọn một api hay một middleware để resize hình ảnh đó có thể với nhiều format. Và nỗ lực xoay sở của bạn cũng không đáp ứng như mong đợi thì lúc đó bạn sẽ phải làm sao? Xin chúc mừng các bạn đã gặp trường hợp như trên, giờ đây khi chúng ta sử dụng Cloudinary thì api sẽ giúp bạn mọi thứ. Vâng chính là mọi thứ. Hình ảnh upload lên Cloudinary sẽ tự động tạo CND, và api của Cloudinary cung cấp toàn diện và dễ dàng tích hợp ở web hay app mobile. Mới sơ qua các bạn thấy sướng chưa. Sướng đúng không, nhưng xem nó có free hay không nhé?

 Cloudnary có free nhé các bạn, nhưng đến giới hạn nào đó thôi. Nhưng nó cũng đủ cho chúng ta xài thoải mái. Cụ thể khi chúng ta đăng ký thành công và sử dụng gói free thì hắng tháng chúng cho ta 25 Credits, và mỗi Credit = 1 GB Storage OR 1 GB Bandwidth. 

Xem hình ảnh để thấy chúng ta quá thoải mái khi chọn Cloudinary.

 Upload images to Cloudinary With Multer in ExpressJS 

OK bây giờ tôi sẽ giúp các bạn upload lên Cloudinary. Như tôi đã nói, tôi sẽ lấy source code của bài "upload files using multer", bạn nào chưa biết hay chưa download code về thì vào bài đó lấy code. Tôi sẽ demo cho các bạn về cách upload single và multiple lên Cloudinary luôn. 

Upload single image Cloudinary With Multer

Khi đăng ký thành công thì bạn có thể lấy 3 tham số để add vào file config api cloudinary đó là

  • Cloud name: xxx 
  • API Key:xxx 
  • API Secret: xxx

Đầu tiên chúng ta sẽ install cloudinary 

$npm i cloudinary --save

 Ở bài trước trong folder models chỉ có ModelMulter.js, thì tôi sẽ tạo thêm một file tên là ModelCloudinary.js

var cloudinary = require('cloudinary').v2;
//lấy trong https://cloudinary.com/console/welcome
cloudinary.config({
    cloud_name: 'xxxx',
    api_key: 'xxxx',
    api_secret: 'xxx'
});

var self = module.exports = {
    uploadSingle: (file) => {
        return new Promise(resolve => {
            cloudinary.uploader.upload(file, {
                    folder: 'single'
                })
                .then(result => {
                    if (result) {
                        const fs = require('fs')
                        fs.unlinkSync(file)
                        resolve({
                            url: result.secure_url
                        })
                    }
                })
        })
    },
    uploadMultiple: (file) => {
        return new Promise(resolve => {
            cloudinary.uploader.upload(file, {
                    folder: 'home'
                })
                .then(result => {
                    if (result) {
                        const fs = require('fs')
                        fs.unlinkSync(file)
                        resolve({
                            url: result.secure_url,
                            id: result.public_id,
                            thumb1: self.reSizeImage(result.public_id, 200, 200),
                            main: self.reSizeImage(result.public_id, 500, 500),
                            thumb2: self.reSizeImage(result.public_id, 300, 300)
                        })
                    }
                })
        })
    },
    reSizeImage: (id, h, w) => {
        return cloudinary.url(id, {
            height: h,
            width: w,
            crop: 'scale',
            format: 'jpg'
        })
    },
}

Để tôi giải thích cho các bạn hiểu hơn về model trên. Khi upload thì cloudinary sẽ cho chúng ta một file gốc ví dụ 

File gốc: https://res.cloudinary.com/dtknxx9ki/image/upload/v1571447099/1540353072753_epknyj.png

Chúng ta có thể crop theo height và width theo mode fill or scale sẽ là: 

Crop scale: https://res.cloudinary.com/dtknxx9ki/image/upload/w_100,h_150,c_scale/v1571447099/1540353072753_epknyj.png  

Crop fill: https://res.cloudinary.com/dtknxx9ki/image/upload/w_100,h_150,c_scale/v1571447099/1540353072753_epknyj.png

Đến đây tôi nghĩ các bạn cũng đã hiểu rồi đúng không

 Cú pháp upload api cloudinary

cloudinary.uploader.upload(file, { folder: 'home'}) 

trong đó file là tham số truyền vào là file img trên host local và được upload bởi multer trong bài trước. 

folder là hình ảnh này được upload vào thư mục nào?

Sau khi upload thành công thì chúng ta sẽ remove hình ảnh trong local của chúng ta, tránh quên sẽ full ổ cứng nha =]] 

fs.unlinkSync(file);// remove img in local 

resolve();// trả về khi thành công của một promise

 Bạn nào chưa biết sử dụng promise thì tìm kiếm trong blog này để hiểu nha. Nếu làm biếng thì click vào đây: https://anonystick.com/search?key=promise 

reSizeImage hàm này chính là hàm resize mà bạn muốn, thoải mái có thể chỉnh tất cả mọi thứ. Đen trắng, chỉ lấy khuôn mặt... Các bạn vào link này để đọc thêm về Cloudinary api nodejs documentation

 Đây là một công cụ quá mạnh mẽ và không tốn tiền. Quá đã. Tiếp theo tôi sẽ tích hợp trong controllerUpload trong folder controllers(nhớ đọc bài trước).

Upload multiple images Cloudinary with Multer

File controllerUpload.js

'use strict';
const cloudinary = require('./models/ModelCloudinary')
var self = module.exports = {
    uploadSingleFile: async(req, res) => {
        //req.file.path chính là đường dẫn của file khi upload bằng multer
        cloudinary.uploadSingle(req.file.path).then((result) => {
            let imageDetails = {
                imageName: req.body.imageName || '',
                cloudImage: result.url,
                imageId: result.id
            }
        })
        
        res.json(req.file)
    },
    //up multiple files
    uploadMultipleFiles: async(req, res) => {
        //req.files chính là khi upload multiple images
        let res_promises = req.files.map(file => new Promise((resolve, reject) => {
            cloudinary.uploadMultiple(file.path).then((result) => {
                resolve(result);
            })
        }))
        
        // Promise.all get imgas
        Promise.all(res_promises)
        .then(async (arrImg) => {
           //arrImg chính là array mà chúng ta đã upload 
           // các bạn có thể sử dụng arrImg để save vào database, hay hơn thì sử dụng mongodb
           res.json(req.files)
        })
        .catch((error) => {
            console.error('> Error>', error);
        })
    },
}

 và tôi cũng dùng postman để test và đây là kết quả:

 Như vậy là xong, giờ đây các bạn có thể sử dụng chúng cho hình ảnh website của bạn. Các bạn có thể download code lại trên github. 

Source code: Github 

Nếu bạn nào không hiểu hoặc chưa làm được, hãy comment hay gửi mail cho mình anonystick@gmail.com. Mình hứa sẽ giúp các bạn một cách nhiệt tình nhất.
Thanks for reading!