Print View,Thaimisc.Com : เล่นกับไฟล์ (6) เล่นกับไฟล์ (6)
Php Developer
เดอะกาฝากไดอารี่ (channelv_on_mobile@hotmail.com) , Date 03-11-2004
หายไปราวๆ เกือบ 2 เดือนเห็นจะได้ครับ ต้องขออภัยจริงๆ

ที่ต้องหายไปก็เป็นเพราะว่า ผมติดสอบครับ... คือนึกอยู่ดีไม่ว่าดี ดันไปลงทะเบียนเรียนปริญญาตรีอีกรอบ ชะรอยว่าคงยังไม่อยากแก่ แหะ แหะ ตอนนี้ก็เลยได้เป็น freshy คณะนิติศาสตร์ มหาวิทยาลัยรามคำแหง สมใจอยาก -_-'' ช่วงเดือนที่ผ่านมา จนถึงวันที่ 2 พฤศจิกายน ซึ่งก็คือเมื่อวานนี้ ผมติดสอบครับ เลยไม่สะดวกที่จะมาอัพเดต

แต่พอสอบเสร็จ เห็นไหมล่ะ ผมรีบมาในบัดดล อิอิ

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

แต่ readfile() นั้น หลักการทำงานของมันคือ การอ่านข้อมูลจากไฟล์ใดๆ ที่เรากำหนด จากนั้นก็ส่งออกมาที่ output buffer ครับ

พอมาถึงคำว่า output buffer แล้วก็พาลให้งง... นั่นมันศัพท์ทางเทคนิคน่ะ แหะ แหะ ที่ผมพยายามพูดถึงศัพท์ทางเทคนิคก่อน นั่นก็เพราะว่า มันเป็นสิ่งที่เราๆ ท่านๆ จะเห็น เวลาที่เปิด PHP Manual อ่าน เลยอยากให้ทำความเข้าใจเอาไว้ก่อน

เอาละ ทีนี้มาสู่คำถามที่ว่า output buffer คืออะไรกันดีกว่า... คำตอบสั้นๆ ง่ายๆ ก็คือ ออกมาเป็นไฟล์ไงล่ะครับ

แต่บางที การพยายามอธิบาย มันเข้าใจได้ยาก และใช้เวลานานกว่าการดูตัวอย่างนะ... งั้นเอางี้ เรากลับไปที่โฟลเดอร์ C:AppServwwwtest ของเรา (เอ ยังจำกันได้อยู่ไหมครับ ว่าการเล่นกับไฟล์ครั้งนี้ ผมสร้างโฟลเดอร์นี้เอาไว้ทดสอบ) แล้วลอง copy ไฟล์อะไรซักอันมาไว้ที่นี่ดีกว่า... ผมจะลอง copy ไฟล์รูปมาซักรูปไว้ในนี้ครับ สมมติให้ชื่อ test.jpg แล้วกัน

รูป test.jpg ก็เป็นประมาณนี้เลยครับ


ไม่ได้มีอะไรกับบทความหรอก แค่อยากโชว์รูปอ่ะ ตลกดี

จากนั้นผมก็สร้างไฟล์ชื่อ download.php แล้วเขียนโค้ดตามนี้

<?php

$file = "test.jpg";
header("Content-Description: File Transfer");
header("Content-Type: application/force-download");
header("Content-Length: " . filesize($file));
header("Content-Disposition: attachment; filename=" . basename($file));
readfile($file);

?>

มาดูคำอธิบายนะครับว่าโค้ดของไฟล์ download.php นั้นมีความหมายยังไง

$file = "test.jpg";

เป็นการกำหนดก่อนว่า งานนี้ตัวแปร $file หมายถึงไฟล์ชื่อ test.jpg และเนื่องจากไม่ระบุ path ให้ แสดงว่าย่อมหมายความว่าไฟล์นั้นอยู่ใน directory เดียวกับไฟล์ download.php นั่นเอง

header("Content-Description: File Transfer");

สร้าง header เพื่อบอกกับบราวเซอร์ว่า เนื้อหาของไฟล์ download.php นี้ คือ File Transfer หรือการดาวน์โหลดไฟล์นั่นเอง

header("Content-Type: application/force-download");

และยังบอกอีกว่า ประเภทของเนื้อหานั้น เป็นการบังคับให้ดาวน์โหลด หรือพูดง่ายๆ พอรันไฟล์ download.php นี้ปุ๊บ จะให้เริ่มถามเลยว่าจะดาวน์โหลด หรือจะเปิดไฟล์นี้ (ดูรูปประกอบ)

header("Content-Length: " . filesize($file));

บรรทัดนี้บอกว่า ขนาดของไฟล์ test.jpg นั้นมีขนาดเท่าไหร่ครับ... เป็น header ที่จำเป็นต้องมี ประมาณนั้นแหละ

header("Content-Disposition: attachment; filename=" . basename($file));

บรรทัดนี้เป็นการกำหนดให้ว่า ชื่อของไฟล์ที่จะดาวน์โหลดไปนั้น จะแสดงออกเป็นชื่อว่าอะไรครับ

readfile($file);

สุดท้ายก็คือพระเอกของเรา ที่จะเป็นการอ่านไฟล์มาเก็บไว้ใน output buffer ของไฟล์ download.php ครับ... ผลก็คือ โค้ดนี้ก็จะทำการอ่านไฟล์ test.jpg ที่เก็บเอาไว้ แล้วส่งออกมาเป็น output buffer ของไฟล์ download.php ซึ่งบังเอิญว่า header ของไฟล์นี้ ถูกกำหนดให้เป็นรูปแบบของ File Transfer ครับ

พอรันไฟล์นี้ ก็เลยกลายเป็นการเริ่มดาวน์โหลดไปนั่นเอง

ถามผมว่า ประโยชน์ของการทำแบบนี้คืออะไร?!? ผมว่าคือการเอาไปประยุกต์เข้ากับระบบดาวน์โหลดครับ คือ แทนที่จะลิงก์ไปยังตัวไฟล์ที่จะให้ดาวน์โหลดโดยตรง เราก็ใช้การอ่านมาเก็บไว้ที่ output buffer แล้วค่อยให้ดาวน์โหลดอีกต่อแทน เท่านี้ คนอื่นเขาก็ไม่รู้แล้ว ว่าเราเก็บไฟล์ที่ให้ดาวน์โหลดเอาไว้ที่ไหน

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

ประเด็นสำคัญก็คือ ต้องดูให้ดีๆ นะครับว่า output buffer นั้นมีเท่าไหร่ ถ้าไฟล์มันเกิดใหญ่เกินกว่าที่จะเก็บลง output buffer ได้ เป็นเรื่องแหง

อันนี้ผมให้ไว้เป็นกรณีศึกษาเท่านั้นครับ แฟนานุแฟนท่านผู้อ่านทุกท่าน คงต้องไปติดตามศึกษาอ่านกันต่อเอาเอง :)