โจทย์ คือต้องการย้ายไฟล์สแกน จำนวนมาก เข้าไปเก็บตาม folder เพื่อทำ sharding storage ซึ่งการสร้าง directory สำหรับจัดเก็บ และการกระจายไฟล์ไปยัง folder นั้นคือหลักสำคัญในการดำเนินการครั้งนี้
Create Directory
ด้วย brief ที่เก็บไฟล์แยกด้วยตัวเลขล้วนๆ ทำให้ง่ายต่อการสร้าง folder โดยหลักการก็คือ แบ่ง folder เป็นเลข 00-99
และในแต่ละ folder ก็สร้าง 00-99
ไว้ด้วย ตามแบบด้านล่าง
storage/
├── 00/
│ ├── 00
│ ├── 01
│ ├── ..
│ └── 99
├── 01/
│ ├── 00
│ ├── 01
│ ├── ..
│ └── 99
├── ..
└── 99/
├── 00
├── 01
├── ..
└── 99
วิธีสร้าง folder ตามแบบฉบับ “ความขี้เกียจเกิดก่อนวัตกรรม” ก็คือเขียนคำสั่งให้มันนั้นเอง โดยใช้ batch ง่ายๆ สร้าง folder เพื่อเก็บขึ้นมาก่อน โดยการวน loop 2 รอบ และให้มันสร้าง folder ตั้งแต่ 1 – 100
FOR /L %N IN (1,1,100) DO ( FOR /L %M IN (1,1,100) DO md "%N\%M" )
พอ run เสร็จก็จะได้ folder 1 – 100 ขึ้นมา เท่านี้ก็เหลือแค่ rename ชื่อ เลข 1 ให้เป็น 01 เลข 100 ให้เป็น 00 เท่านั้น
Move File with nodejs
หลังจากสร้าง folder เสร็จแล้ว เราก็มาย้ายไฟล์สแกนทั้งหมดเข้าไปเก็บตาม folder ของมันได้เลย โดยเงื่อนไขก็คือ ชื่อไฟล์จะเป็นตัวเลข 9 หลัก 000000000.pdf
- สีเหลือง = storage/xx
- สีเขียว = storage/xx/xx
โดยวิธีเก็บแบบนี้จะใช้ 2 หลักท้าย มาเป็น folder แรก และ 2 หลักต่อมา เป็น sub-folder นั่นเอง สมมุติ ชื่อไฟล์คือ 000123456.pdf ก็จะได้ path เก็บไฟล์แบบนี้ storage/56/34/000123456.pdf
เมื่อรู้เงื่อนไขแล้วก็มาเขียน code สำหรับโยนไฟล์กันได้แล้ว เลือกใช้ nodejs เนื่องจากมันค่อนข้างง่าย และ server ที่เก็บไฟล์ก็เป็น Linux ด้วย จะตั้ง cronjob ให้มันโยนไฟล์ตอนไหนก็ทำได้
const fs = require("fs");
const mv = require('mv');
const path = require("path");
const dotenv = require("dotenv").config();
const srcFolder = process.env.SOURCE_PATH;
const descFolder = process.env.DESTINATION_PATH;
// read all files in the directory
let files = fs.readdirSync(srcFolder);
// Loop through array and rename all files
files.forEach((file, index) => {
let fullPath = path.join(srcFolder, file);
if (path.extname(file) == ".pdf") {
let fname = path.basename(file, ".pdf");
if (fname.length == 9) {
let folder = `${fname.slice(7, 9)}/${fname.slice(5, 7)}/${file}`;
try {
mv(fullPath, path.join(descFolder, folder), () => {
console.log(index, fullPath, path.join(descFolder, folder));
// console.log(err);
})
} catch (error) {
console.error(error)
}
}
}
});
ไฟล์ .env
#Development Env
NODE_ENV = 'development'
SOURCE_PATH = '/path_of/source'
DESTINATION_PATH = '/path_of/destination'
package.json
{
"name": "@service/nodejs-sharding-storage",
"version": "1.0.0",
"description": "nodejs file sharding storage",
"main": "src/app.js",
"scripts": {
"start": "node ./src/app.js",
"dev": "nodemon --watch src ./src/app.js"
},
"dependencies": {
"dotenv": "^8.2.0",
"mv": "^2.1.1"
},
"devDependencies": {
"nodemon": "^2.0.6"
}
}
สรุป
วิธีการข้างต้นนั้น ทำแต่การโยนไฟล์ไปเก็บเท่านั้น ตัวโปรแกรมก็ยังสามารถเพิ่มความสามารถในการบันทึกข้อมูลลงใน database ได้ ว่าไฟล์ไหนเก็บไปแล้วบ้าง เก็บเมื่อไหร่ และสามารถใช้ node-cron เพื่อสั่งให้มันทำงานเองอัตโนมัติ ตามเวลายิ่งสะดวกเข้าไปใหญ่