File Server với Multer, Express trong NodeJS

Thông thường các tập tin được upload lên server, chúng được mã hóa như multipart/form-data. Multer là một middleware cho Express và NodeJS, nó giúp dễ dàng xử lý mã hóa multipart/form-data. Trong bài viết này tôi sẽ hướng dẫn các bạn xây dựng file server dựa trên Multer, Express.


  • NodeJS v8.11.4
  • NPM v5.6.0

Chúng ta sẽ bắt đầu khởi tạo project với các lệnh sau:

mkdir fstack-file-server
cd fstack-file-server
npm init

Các bạn cung cấp các thông tin cần thiết theo hướng dẫn

Chúng ta sẽ tạo thêm các file: index.js, file-util.js, upload.js.env. Lúc này Cấu trúc project lúc này như hình bên dưới:

package.json

{
  "name": "fstack-file-server",
  "version": "1.0.0",
  "description": "file upload/download with multer, express in nodejs",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/thitranthanh/fstack-file-server.git"
  },
  "keywords": [
    "file",
    "server"
  ],
  "author": "thitranthanh@gmail.com",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/thitranthanh/fstack-file-server/issues"
  },
  "homepage": "https://github.com/thitranthanh/fstack-file-server#readme",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^8.0.0",
    "express": "^4.17.1",
    "mime": "^2.4.4",
    "multer": "^1.4.1",
    "rimraf": "^2.6.3",
    "sharp": "^0.22.1",
    "uuid": "^3.3.2",
    "yargs": "^13.3.0"
  }
}

index.js

'use strict';

require('dotenv').config();
const express = require('express');
const argv   = require('yargs').argv
const bodyParser = require('body-parser');
const path = require('path');
const mime = require('mime');
const upload = require('./upload');
const FileUtil = require('./file-util');

const fs = require('fs');
const cors = require('cors');

const app = express();
const port = process.env.server_port || 3000;

app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));

app.use(express.static('public'));

app.post('/upload', upload.single('file'), async function (req, res) {
    const filePath = path.join(__dirname, '/public/images');
    const fileUpload = new FileUtil(filePath);
    if (!req.file) {
      console.log('400 Bad request: please provide an image');
      res.status(400).json({error: 'Please provide an image'});
    }
    const extention = mime.getExtension(req.file.mimetype);
    const filename = await fileUpload.save(req.file.buffer, extention);
    return res.status(200).json({ name: filename +'.' + extention });
  });

app.listen(port, function () {
    let dir = path.join(__dirname, '/public');
    if (!fs.existsSync(dir)){
        fs.mkdirSync(dir);
    }
    dir = path.join(__dirname, '/public/images');
    if (!fs.existsSync(dir)){
        fs.mkdirSync(dir);
    }
    console.log('Server is running on port ' + port);
});

// catch all exception
process.on('uncaughtException', function(err) {
    console.log('Caught exception: ' + err);
});

file-util.js

'use strict';

require('dotenv').config();
const sharp = require('sharp');
const uuidv4 = require('uuid/v4');
const path = require('path');

class FileUtil {
  constructor(folder) {
    this.folder = folder;
  }
  async save(buffer, mineType) {
    const filename = FileUtil.filename();
    const filepathOriginal = this.filepath(filename + '.' + mineType);

    await sharp(buffer)
      .toFile(filepathOriginal);
    
    return filename;
  }
  static filename() {
    return `${uuidv4()}`;
  }
  filepath(filename) {
    return path.resolve(`${this.folder}/${filename}`)
  }
}
module.exports = FileUtil;

upload.js

'use strict';

require('dotenv').config();
const multer = require('multer');
const MAX_FILE_SIZE = process.env.max_file_size || 2;
const upload = multer({
  limits: {
    fileSize: MAX_FILE_SIZE * 1024 * 1024
  }
});

module.exports = upload;

.env

server_port=3000
max_file_size=2
  • server_port: cấu hình listening port cho file server
  • max_file_size: giới hạn kích thước tập tin upload, đơn vị là MB

Bây giờ chúng ta cài đặt các thư viện với lệnh: npm install

npm install

Start server và dùng postman để kiểm tra tính năng upload

node index.js

Tải và cài đặt Postman ở link

https://www.getpostman.com/downloads/

Mở postman và upload file

Chú ý: ở bước 4 trong hình các bạn nhập key là ‘file‘ và chọn type là ‘File‘ sau đó chọn file cần upload

Sau khi có response ở bước 5, chúng ta sao chép name và open link:

http://localhost:3000/images/95abb3ec-90ef-4e87-9d56-28dde3f3c647.jpeg

Source đầy đủ của ví dụ trong bài này có thể download trên Github qua link bên dưới:

https://github.com/thitranthanh/fstack-file-server