การคัดลอกไฟล์ใน Node.js

6 December 2023

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

  • ฟังก์ชัน fs.copyFile()
  • ฟังก์ชัน fs.copyFileSync()
  • ฟังก์ชัน fsPromises.copyFile()
  • โหมดในการคัดลอกไฟล์

ฟังก์ชัน fs.copyFile()

ฟังก์ชันพื้นฐานสำหรับคัดลอกไฟล์ใน Node.js คือฟังก์ชัน fs.copyFile() ซึ่งจะใช้งานในรูปแบบ Asynchronous ที่รับฟังก์ชัน Callback เมื่อการทำงานเสร็จสิ้น นี่เป็นรูปแบบการใช้งาน

fs.copyFile(src, dest[, mode], callback);
  • src: พาธของไฟล์ต้นทางสำหรับคัดลอก
  • dest: พาธของไฟล์ปลายทางสำหรับคัดลอก
  • mode: โหมดในการคัดลอก
  • callback: ฟังก์ชันที่จะถูกเรียกเมื่อการคัดลอกเสร็จสิ้น

นี่เป็นตัวอย่างการใช้งานฟังก์ชัน fs.copyFile() สำหรับคัดลอกไฟล์อย่างง่ายใน Node.js

copy_file_callback.js
const fs = require("fs");

fs.copyFile("source.txt", "destination.txt", (err) => {
    if (err) {
        console.log(err.message);
    } else {
        console.log("source.txt was copied to destination.txt");
    }
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

source.txt was copied to destination.txt

ในตัวอย่างนี้ เราได้เขียนโปรแกรมเพื่อคัดลอกไฟล์ใน Node.js โดยคัดลอก Text ไฟล์ที่มีชื่อว่า source.txt ไปยังไฟล์ destination.txt ที่อยู่ในโฟล์เดอร์เดียวกัน และหลังจากที่โปรแกรมถูกรันเราจะได้รับสองไฟล์ที่มีเนื้อหาเหมือนกัน

ฟังก์ชัน Callback จะรับหนึ่งพารามิเตอร์คือ err ซึ่งจะเป็นออบเจ็ค Error ในกรณีที่มีข้อผิดพลาดเกิดขึ้นในระหว่างการคัดลอกไฟล์หรือ null ในกรณีที่ไม่มีข้อผิดพลาด

ในการเรียกใช้ฟังก์ชันเพื่อคัดลอกไฟล์ ไฟล์ต้นทางจะต้องมีอยู่จริงเสมอไม่เช่นนั้นจะเกิดข้อผิดพลาดขึ้น นี่เป็นตัวอย่างของการคัดลอกไฟล์ no_file.txt ที่ไม่มีอยู่ (คุณจะต้องลบมันออกก่อนรันโปรแกรม)

copy_file_callback2.js
const fs = require("fs");

fs.copyFile("no_file.txt", "destination.txt", (err) => {
    if (err) {
        console.log(err.message);
    } else {
        console.log("source.txt was copied to destination.txt");
    }
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรมที่จะแสดงเป็นข้อความผิดพลาดแทน

NOENT: no such file or directory, copyfile 'C:\nodejs\no_file.txt' -> 'C:\nodejs\destination.txt'

ฟังก์ชัน fs.copyFileSync()

ฟังก์ชัน fs.copyFileSync() เป็นฟังก์ชันอีกเวอร์ชันสำหรับคัดลอกไฟล์ที่ทำงานในรูปแบบ Synchronous ตามชื่อของมัน ซึ่งจะบล็อกการทำงานของโปรแกรมจนกว่าการคัดลอกจะเสร็จ นี่เป็นรูปแบบการใช้งาน

fs.copyFileSync(src, dest[, mode]);
  • src: พาธท์ของไฟล์ต้นทางสำหรับคัดลอก
  • dest: พาธท์ของไฟล์ปลายทางสำหรับคัดลอก
  • mode: โหมดในการคัดลอก

สำหรับรูปแบบการใช้งานจะเหมือนกับฟังก์ชัน fs.copyFile() ยกเว้นมันไม่มีพารามิเตอร์ callback เนื่องจากโปรแกรมจะทำงานคำสั่งนี้ให้เสร็จก่อนค่อยทำคำสั่งต่อไป และกรณีเกิดข้อผิดพลาดฟังก์ชันจะ throw ข้อผิดพลาดขึ้น นี่เป็นตัวอย่างการใช้งาน

copy_file_sync.js
const fs = require("fs");

try {
    fs.copyFileSync("source.txt", "destination.txt");
    console.log("source.txt was copied to destination.txt");
} catch (err) {
    console.log(err.message);
}

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

source.txt was copied to destination.txt

ผลลัพธ์ที่ได้ของโปรแกรมจะเหมือนกับตัวอย่างก่อนหน้าแต่แตกต่างกันที่วิธีทำงานเบื้องหลัง แบบแรกทำงานแบบ Asynchronous ที่ต้องการฟังก์ชัน Callback เมื่อการทำงานเสร็จสิ้น ส่วนแบบที่สองทำงานแบบ Synchronous และบล็อคการทำงานของโปรแกรมอยู่แล้วจึงไม่ต้องการ

ฟังก์ชัน fsPromises.copyFile()

ฟังก์ชันสุดท้ายสำหรับคัดลอกไฟล์เป็นฟังก์ชัน fsPromises.copyFile() จากโมดูล fs/promise โดยการทำงานของฟังก์ชันจะเป็นแบบ Promise นี่เป็นรูปแบบการใช้งาน

fsPromises.copyFile(src, dest[, mode]);
  • src: พาธท์ของไฟล์ต้นทางสำหรับคัดลอก
  • dest: พาธท์ของไฟล์ปลายทางสำหรับคัดลอก
  • mode: โหมดในการคัดลอก

ฟังก์ชันนี้จะส่งค่ากลับเป็น Promise เมื่อการทำงานเสร็จสิ้น ดังนั้นเราสามารถใช้มันในรูปแบบของ Promise หรือร่วมกับคำสั่ง async/await ได้ นี่เป็นตัวอย่างการใช้งาน

copy_file_promise.js
const fsPromises = require("fs/promises");

fsPromises.copyFile("source.txt", "destination.txt").then(() => {
    console.log("source.txt was copied to destination.txt");
}).catch((err) => {
    console.log(err.message);
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

source.txt was copied to destination.txt

เนื่องจากฟังก์ชันส่งค่ากลับเป็น Promise ดังนั้นเราสามารถใช้ร่วมกับคำสั่ง async/await เพื่อการคัดลอกเป็นแบบ Synchronous ได้ ซึ่งให้ผลลัพธ์เช่นเดียวกับตัวอย่างก่อนหน้า

copy_files_async_await.js
const fsPromises = require("fs/promises");

(async () => {
    try {
        await fsPromises.copyFile("source.txt", "destination.txt");
        console.log("source.txt was copied to destination.txt");
    } catch (err) {
        console.log(err.message);
    }
});

โหมดในการคัดลอกไฟล์

สำหรับพารามิเตอร์ mode ที่ใช้สำหรับกำหนดโหมดในการคัดลอกไฟล์ หากไม่ได้ระบุจะมีค่าเริ่มต้นเป็น fs.constants.COPYFILE_EXCL | fs.constants.COPYFILE_FICLONE ซึ่งหมายความว่าหากปลายทางมีไฟล์อยู่แล้วจะเขียนทับไปเลย นี่เป็นโหมดคัดลอกไฟล์ทั้งหมดที่สามารถใช้ได้สำหรับฟังก์ชันคัดลอกไฟล์ที่ได้กล่าวมาแล้ว

  • fs.constants.COPYFILE_EXCL: การคัดลอกจะเกิดข้อผิดพลาดถ้าหากไฟล์ปลายทางมีอยู่แล้ว (โหมดปกติ)
  • fs.constants.COPYFILE_FICLONE: การคัดลอกจะทำแบบ copy-on-write หากระบบรองรับ หากไม่รองรับจะใช้โหมดปกติแทน
  • fs.constants.COPYFILE_FICLONE_FORCE: การคัดลอกจะทำแบบ copy-on-write ถ้าหากระบบรองรับ หากไม่รองรับจะเกิดข้อผิดพลาดขึ้น

ต่อไปมาดูตัวอย่างการใช้งานพารามิเตอร์ mode สำหรับป้องกันการคัดลอกทับไฟล์เดิม หากพาธปลายทางที่ระบุเป็นไฟล์ที่มีอยู่แล้ว

copy_file_with_mode.js
const fs = require("fs");

fs.copyFile("source.txt", "destination.txt", fs.constants.COPYFILE_EXCL, (err) => {
    if (err) {
        console.log(err.message);
    } else {
        console.log("source.txt was copied to destination.txt");
    }
});

นี่เป็นผลลัพธ์การทำงานของโปรแกรม

EEXIST: file already exists, copyfile 'C:\nodejs\source.txt' -> 'C:\nodejs\destination.txt'

นี่เป็นตัวอย่างของการรันโปรแกรมสองครั้งและในครั้งที่สองจะเกิดข้อผิดพลาดขึ้นเนื่องจากมันได้คัดลอกไปแล้วในการรันครั้งแรก คุณสามารถใช้โหมดนี้เพื่อป้องกันการเขียนทับไฟล์เดิมในระหว่างการคัดลอกไฟล์ได้

ในบทนี้ คุณได้เรียนรู้เกี่ยวกับการเขียนโปรแกรมเพื่อคัดลอกไฟล์ใน Node.js โดยการใช้ฟังก์ชันจากโมดูล fs ซึ่งมีฟังก์ชันในรูปแบบต่างๆ ให้ใช้งานไม่ว่าจะเป็นฟังก์ชันแบบ Callback, Synchronous หรือ Promise คุณสามารถเลือกวิธีที่เหมาะสมกับการทำงานของคุณได้

บทความนี้เป็นประโยชน์หรือไม่?Yes·No