เขียนโปรแกรมดาวน์โหลดรูปภาพและวีดีโอด้วย Node.js

Node.js เป็น Framework ที่มีความสามารถด้าน Networking และ Internet พร้อมใช้งานทันทีโดยไม่จำเป็นต้องติดตั้ง Package เพิ่มเติม โดยบทความนี้จะสาธิตการเขียนโปรแกรมสำหรับดาวน์โหลดรูปภาพและวีดีโอโดยการใช้ Core Module ของ Node.js ซึ่งเมื่อเข้าใจหลักการเขียนโปรแกรมตามในบทความแล้ว ผู้อ่านก็จะสามารถนำไปต่อยอดในการเขียนโปรแกรม Web Scraping ได้เช่นกันครับ

ลำดับการทำงานของโปรแกรม

  1. ส่ง HTTP Request ไปยังเซิร์ฟเวอร์
  2. รับ Raw Data จากเซิร์ฟเวอร์ และนำมา Manipulate Stream
  3. บันทึก Stream ลงดิสก์

เตรียมไฟล์สำหรับเขียนโปรแกรม

Path

|-package.json
+-src
|   |-index.js

ไฟล์ package.json

{
    "scripts": {
        "dev": "node src"
    }
}

พิมพ์คำสั่งที่ Terminal

# ทดสอบการรันโปรแกรม
npm run dev

คลังรูปภาพและวีดีโอ

ตัวอย่างลิงค์สำหรับดาวน์โหลดรูปภาพ ทั้งภาพนิ่ง ภาพเคลื่อนไหว และวีดีโอสามารถหาได้จากเว็บไซต์ https://imgur.com/ ครับ

HTTP Request

ในการส่ง HTTP Request นั้น เราจะใช้ Module ชื่อ https ซึ่งเป็น Core Module ที่มาพร้อมกับ Node.js อยู่แล้วครับ ซึ่งคำสั่ง https.request() ถูก Implement ในรูปแบบของ Callback เราจึงไม่สามารถเขียนโค้ดในแบบ async/await ได้ครับ

// เรียกใช้ module
const https = require('https')
// ตัวอย่าง permalink จากเว็บ imgur.com ครับ
const url = 'https://i.imgur.com/UDkB5M4.mp4'

// ส่ง request ไปยังเซิร์ฟเวอร์
https.request(url, res => {
    // เกิด event ระหว่างรับข้อมูลจากเซิร์ฟเวอร์
    res.on('data', chunk => {
        // ...
    })

    // เกิด event เมื่อรับข้อมูลจากเซิร์ฟเวอร์เสร็จสิ้น
    res.on('end', () => {
        console.log('Finished')
    })

    // แสดงข้อความ error
    res.on('error', err => {
        console.log(err.message)
    })
}).end()

Stream Manipulation

จากขั้นตอนที่ผ่านมา ข้อมูลที่ส่งมาจากจากเซิฟเวอร์นั้น จะถูกส่งมาเป็น Chunk จำนวนหลายครั้ง ในขั้นตอนนี้จะเป็นการนำ Chunk เหล่านั้นมาต่อเติมเป็น Stream ไปเรื่อยๆ ครับ ซึ่ง Node.js ก็มี Core Module รองรับการจัดการกับ Stream ไว้พร้อมแล้วเช่นกันครับ

ไฟล์ src/index.js

// เรียกใช้ module
const Stream = require('stream').Transform

https.request(url, res => {
    // สร้าง instance ของ stream
    const stream = new Stream()

    res.on('data', chunk => {
        // รับข้อมูลจากเซิร์ฟเวอร์และต่อเติม Stream ไปเรื่อยๆ
        stream.push(chunk)
    })
}).end()

บันทึก Stream

ขั้นตอนสุดท้ายจะเป็นการบันทึก Stream ลงสู่ Disk ซึ่งในขั้นตอนนี้เราจะใช้งาน Core Module ที่ชื่อ fs ครับ

ไฟล์ src/index.js

// เรียกใช้ module
const fs = require('fs')

https.request(url, res => {
    // บันทึก stream เมื่อรับข้อมูลจากเซิร์ฟเวอร์เสร็จสิ้น
    res.on('end', () => {
        // ใช้ regular expression เพื่อ extract ชื่อไฟล์และนามสกุลจาก url
        const pattern = /(\w+\.)+\w+$/
        const filename = url.match(pattern)[0]

        // เขียน stream ลง disk
        fs.writeFileSync(filename, stream)
    })
}).end()

โค้ดทั้งหมด

ไฟล์ src/index.js

const https = require('https')
const Stream = require('stream').Transform
const fs = require('fs')

const url = 'https://i.imgur.com/UDkB5M4.mp4'

https.request(url, res => {
    const stream = new Stream()

    res.on('data', chunk => {
        stream.push(chunk)
    })

    res.on('end', () => {
        const pattern = /(\w+\.)+\w+$/
        const filename = url.match(pattern)[0]

        fs.writeFileSync(filename, stream)
    })

    res.on('error', err => {
        console.log(err.message)
    })
}).end()

つづく