ทำระบบอัพโหลดไฟล์ด้วย Node.js

บทความนี้จะพูดถึงตัวอย่างการทำไฟล์อัพโหลดด้วยการใช้ Node.js + Express.js ร่วมกับ Middleware ของ Express.js ด้วย Multer สำหรับบทความนี้จะมีเทคโนโลยีที่เกี่ยวข้องดังนี้
Step 1 : Create Project
เริ่มต้นทำการสร้างโฟลเดอร์ขึ้นมาใหม่ จากนั้นสร้างไฟล์ package.json
ขึ้นมา (หรือจะใช้คำสั่ง npm init
ก็ได้)
mkdir file-uploadcd file-uploadtouch package.json
ที่ไฟล์ package.json
ตั้งชื่อโปรเจ็คและกำหนดเวอร์ชัน ผมกำหนดไว้แบบนี้
{ "name": "file-upload", "version": "0.0.1"}
ต่อมาติดตั้ง dependencies ที่จะใช้ คือ express และ multer
npm install express multer --save-dev
ไฟล์ package.json
หลังจากที่ติดตั้ง dependencies เรียบร้อยแล้วจะได้ดังนี้
{ "name": "file-upload", "version": "0.0.1", "devDependencies": { "express": "^4.12.3", "multer": "^0.1.8" }}
Step 2 : index.html
ต่อมาทำการสร้างไฟล์ index.html
ขึ้นมา ในส่วนนี้จะไม่ใช้ Template Engine เช่น Jade นะครับ เพราะว่าเป็นแค่ไฟล์อัพโหลดธรรมดา หน้าตา index.html
ก็มีแค่นี้เอง
<!doctype html><html> <head> <meta charset="UTF-8" /> <title>Sample File Upload</title> </head> <body> <form action="/upload" method="post" enctype="multipart/form-data"> <input type="file" name="file" /> <input type="submit" value="Upload" /> </form> </body></html>
กำหนด form
ไปที่ /upload
แบบ POST
และกำหนดเป็น enctype="multipart/form-data"
โดยในส่วนไฟล์อัพโหลด เราจะใช้ input
เป็นแบบ file
Step 3 : server.js
ต่อมาในส่วน server.js
ทำการเขียนโค๊ดเพื่อกำหนด route และรับ request & response ด้วย express.js แบบนี้
var express = require('express')var app = express()
app.get('/', function (req, res) { res.sendFile(__dirname + '/index.html')})
app.post('/upload', function (req, res) { res.send(req.files)})
app.listen(5555, function () { console.log('App running on port 5555')})
ทดสอบรันเซิฟเวอร์ดู
node server.js
จากนั้นเข้าเว็บ http://localhost:5555 และทำการอัพโหลดไฟล์หรือรูปภาพดู สังเกตผลลัพธ์
จะเห็นว่า ยังไม่มี result อะไรออกมา เนื่องจากตัว Express.js โดย default แล้ว มัน handle เฉพาะ urlencoded และ JSON ไม่รวม multipart ฉะนั้นต้องใช้ middleware อย่าง multer มาช่วย
Step 4 : Use multer
ที่ไฟล์ server.js
ทำการ require multer เข้ามา จากนั้นเพิ่มโค๊ด
app.use(multer());
server.js
จะได้เป็นแบบนี้
var express = require('express')var multer = require('multer')
var app = express()app.use(multer())
app.get('/', function (req, res) { res.sendFile(__dirname + '/index.html')})
app.post('/upload', function (req, res) { res.send(req.files)})
app.listen(5555, function () { console.log('App running on port 5555')})
จากนั้นทำการ restart server อีกครั้ง ทดสอบอัพโหลดไฟล์ กด Upload ก็จะเห็นผลลัพธ์แสดงเป็นไฟล์ JSON แบบนี้
{ "file": { "fieldname": "file", "originalname": "sample.png", "name": "02d6a43b22b6cd220336bc35d4e93c6b.png", "encoding": "7bit", "mimetype": "image/png", "path": "/tmp/02d6a43b22b6cd220336bc35d4e93c6b.png", "extension": "png", "size": 3947, "truncated": false, "buffer": null }}
จะเห็นได้ว่า ไฟล์ที่เราอัพโหลด เราสามารถรู้ค่า properties ได้ อย่างเช่น
originalname
: ชื่อไฟล์ที่เราอัพโหลดname
: ชื่อไฟล์หลังจากที่อัพโหลดmimetype
: ชนิดของไฟล์path
: location ที่เก็บไฟล์หลักจากถูกอัพโหลด (default น่าจะถูกเก็บไว้ที่ temp)extension
: นามสกุลไฟล์
ที่นี้เราจะทำอะไรกับไฟล์ที่อัพโหลดก็สามารถทำได้
ถ้าเป็นระบบจริงๆ เมื่อทำการอัพโหลดไฟล์ควรจะกำหนดสิทธิ์ หรือลบออกจาก file system ไม่เช่นนั้น server คุณอาจจะถูก bomb จากการอัพโหลดไฟล์เข้ามาจนเซิฟเวอร์ล่มได้ :)
Step 5 : Multer Configuration
สุดท้าย เราสามารถที่จะกำหนดค่า multer ต่างๆได้ เช่น
- เปลี่ยนชื่อไฟล์ที่อัพโหลด โดย generate ตาม timestamp
- กำหนด path ที่เก็บไฟล์ เช่น ไว้ที่โฟลเดอร์
/uploads
- จำกัดขนาดไฟล์ให้ไม่เกิน 1 MB
ที่ไฟล์ server.js
ตรงส่วน app.use(multer());
เราสามารถส่ง object ที่ใช้กำหนดค่าได้แบบนี้
var fs = require('fs')
app.use( multer({ dest: __dirname + '/uploads/', rename: function (fieldname, filename) { return Date.now() }, limits: { fileSize: 100000 }, onFileSizeLimit: function (file) { console.log('Failed: ' + file.originalname + ' is limited') fs.unlink(file.path) } }))
dest
: ไว้กำหนด location ที่เก็บไฟล์rename
: เปลี่ยนชื่อไฟล์ที่อัพโหลดlimits
: ไว้กำหนด limit ต่างๆ เช่น ขนาดไฟล์ ความยาวชื่อไฟล์ เป็นต้นonFileSizeLimit
: ฟังค์ชันที่ทำงานเมื่อไฟล์เกินลิมิตที่กำหนด
ทีนี้เวลาอัพโหลดไฟล์ลงไปใหม่ path ที่เก็บไฟล์ ชื่อไฟล์ ก็จะถูกเปลี่ยนตามที่เรากำหนด options ไว้ครับ
สุดท้าย ไฟล์ server.js
เป็นแบบนี้ครับ
var express = require('express')var multer = require('multer')var fs = require('fs')
var app = express()
app.use( multer({ dest: __dirname + '/uploads/', rename: function (fieldname, filename) { return Date.now() }, limits: { fileSize: 100000 }, onFileSizeLimit: function (file) { console.log('Failed: ' + file.originalname + ' is limited') fs.unlink(file.path) } }))
app.get('/', function (req, res) { res.sendFile(__dirname + '/index.html')})
app.post('/upload', function (req, res) { res.send(req.files)})
app.listen(5555, function () { console.log('App running on port 5555')})
สรุป
ตัวอย่างนี้ก็เป็นการทำไฟล์อัพโหลดแบบง่ายๆ ด้วยวิธีของผมเองนะครับ ไม่ชัวร์ว่าจะเป็น Best Practice หรือเปล่า ด้วย Node.js + Express.js + Multer เท่านั้นครับ หากมีตรงไหนผิดพลาด แนะนำเพิ่มเติมได้ครับ หรือหากต้องการรายละเอียดเพิ่มเติม ก็สามารถอ่านได้ที่ references
References
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust