// file: testDl.php
<?php
$mimeType = "image/jpeg";
$sourceFileName = "./zealot.jpg"
$destinationFileName = "zealot-from-phpzealots.jpg";
header("Content-type: ".$mimeType."");
header("Content-Disposition: attachment; filename=".$destinationFileName."");
echo file_get_contents($sourceFileName);
// ... and do something as you want such as keep the download stat for this file...
?>
เท่านี้ browser ก็จะขึ้น dialogbox สำหรับดาวน์โหลด แทนที่เราจะ link ไปหาไฟล์ตรงๆ

แต่บางครั้ง อาจจะใส่
header("Cache-Control: max-age=600");
header("Expires: ".date("r", mktime(0,0,0, date("m"),date("d")+7,date("Y")))."");
ไปด้วย เพื่อจัดการพวก Cache-Control ซึ่งเคยเจอปัญหาใน IIS ถ้าไม่ใส่ แบบนี้เข้าไป แล้วมีปัญหา เช่น Cache expired บ้าง ซึ่งคงเกี่ยวกับการ config ตัว IIS มั้ง แต่ผม config ไม่เป็น ก็เลยใส่ code ข้างต้นไว้ เพื่อแก้ปัญหา แต่บน Apache ไม่เคบพบปัญหาอะไร แต่อย่างไร
- roteee's blog
- Login to post comments
- 1344 reads
เช่น การ ตรวจสอบ ว่า User Download ไฟล์ ไปเสร็จ แล้ว
จริงๆ เหรอ ? หรือเปล่า ? กรณี ไม่เสร็จ ถ้าจะ resume ทำไง ? ทำได้หรือเปล่า ??
ถ้าถามผิดประเ้ด็น
[จริงๆ แล้ วควร จะถาม อะไร ที่เป็น PHP Basics ]
ก็ขออภัยอย่างแรงคับ :)
ผมเคยสนใจและศึกษาเรื่องนี้อย่างแรงอยู่พักหนึ่ง พบว่า ... PHP3, PHP4 จะตรวบสอบอย่างนี้ไม่ได้เลย หรือได้ แต่ผมไม่รู้ก็ไม่ทราบ แต่ผมค้น และทดลอง ทดสอบอย่างหนัก ก็ไม่มีทางที่จะเป็นไปได้เลย แต่พบว่า java servlet, jsp กลับสามารถทำได้ โดยถ้า connection ของการดาวน์โหลดนั้นหลุดไป เช่นตอนที่ผมทำเทส ผมพยายามดาวน์โหลดไฟล์ภาพขนาดใหญ่ แล้วกด Stop ที่ Browser แล้วพบว่า เกิด Exception ขึ้นให้เห็น และดักจับได้ ...
แต่ใน PHP5 ที่เป็น Full OO นั้นไม่เคยลองเลยครับ อาจจะทำได้ก็ได้น้ะคับ คุณ pomcob ลองดู และได้ผลยังงัย แจ้งด้วยน้ะคับ :D
กำลังจะถามเลย โดนตัดหน้าซะงั้น
ก่อนออกจาก dif ได้จับงานที่จะทำเว็บขายเพลง mp3 โดยมีเงื่อนไขข้อหนึ่งว่า
ต้องสามารถตรวจสอบได้ว่า user ได้ดาวโหลดไฟล์นั้น เรียบร้อยหรือยัง เพื่อที่จะทำงาน
... ต่อไป
ครั้งนั้นเขียนด้วย java/jsp ผมทำงานในลักษณะนี้
try
{
//send data to client
//ไม่แตกต่างจาก php ที่โรตีบอก
}
catch(ConnectionException e)
{
// exception จะหล่นมา ณ จุดนี้ถ้าหาก user กดปุ่มยกเลิกการดาวโหลดไฟล์
}
// Success statment
สำหรับ phh5 ผมคิดว่าคงใช้งานแบบเดียวกันได้ แต่สำหรับ php4 นี่
ยังคิดไม่ออกเหมือนกันครับ แต่เคยคิดว่า ถ้าทำได้ คำตอบน่าจะอยู่ที่
set_error_handler
ฝากโปร zealot หาคำตอบละกัน :)
Surachai Tepkhumdee
เท่าที่ผมเคยทดสอบดู พบว่า เวลาที่ connection ในการดาวน์โหลดขาดไป PHP4 จะไม่เกิด error exception ไปที่ set_error_handler() ทำให้เราดักจับไม่ได้
และเท่าที่ใช้งาน ผมเข้าใจว่า set_error_handler() นี้ใช้สำหรับดักจับ และจัดการ error ต่างๆ ที่เกินขึ้นขณะที่ php interpreter ทำงาน แต่ถ้า connection ของการดาวน์โหลดที่หลุดไปนั้น ผมเข้าใจว่า interpreter ของ php ไม่ได้มองว่าเป็น error อะไร ก็เลยดักจับไม่ได้ที่ set_error_handler()
หรือไม่ อย่างไร ??
Code
--------------------
<?php
date_default_timezone_set("Asia/Bangkok");
$fp = fopen("myDl.log", "a+");
fwrite($fp, "[".date("Y-m-d H:i:s")."]");
fwrite($fp, "Downloading start...\n");
$myZipFile = "./myDl.zip";
try
{
header("Content-type: application/zip");
header("Content-Disposition: attachment; filename=myDl.zip");
header("Content-Length: ".filesize($myZipFile));
//echo file_get_contents("./myDl.zip");
$outFp = fopen($myZipFile, "r");
$lineCounter = 0;
while(!feof($outFp))
{
echo fgets($outFp, 1024);
$lineCounter++;
fwrite($fp, "Line ".$lineCounter." has been taken...\n");
}
fclose($outFp);
}
catch (Exception $e)
{
fwrite($fp, "[".date("Y-m-d H:i:s")."]");
fwrite($fp, $e->getMessage()."\n\n");
}
fwrite($fp, "[".date("Y-m-d H:i:s")."]");
fwrite($fp, "Done...\n\n\n");
fclose($fp);
?>
Result (จาก log file)
--------------------
[2007-06-16 08:20:18]Downloading start...
Line 1 has been taken...
Line 2 has been taken...
Line 3 has been taken...
.
.
.
Line 3011 has been taken...
ผลปรากฏว่า พอ connection การดาวน์โหลดขาด app ก็หยุดทำงานไปเฉยๆ ไม่ได้ตี exception ออกมา เข้าใจว่าทำงานถึง loop while พอเราตัด connection ตัว php interpreter ก็หยุดทำงาน โดยไม่ได้ตี error อะไรออกมา เข้าใจว่า interpreter มองว่า ก็ไม่ได้เกิด error อะไรนิ๊...
ในขณะเดียวกัน ถ้าเปลี่ยนจาก fopen(), while(), fgets() แต่เปลี่ยนเป็น readfile(), file_get_contents() พอกด Stop การดาวน์โหลด ใน log จะเห็น
[2007-06-16 08:20:18]Done...
คือโปรแกรมทำงานจนจบ ... แต่ในความเป็นจริงแล้ว การดาวน์โหลดยังไม่จบ
ผมเข้าใจว่าตัว php interpreter มองว่า ฟังก์ชั่น ไม่ว่าจะเป็น readfile(), file_get_contents() นั้นทำงานเสร็จแล้ว แต่การแสดง output ยังไม่เสร็จ ก็จะรอ ... จนกว่า output จะเสร็จ และพอ output เสร็จ (การดาวน์โหลดเสร็จ หรือกด Stop ดาวน์โหลด) ก็ทำงานในบรรทัดต่อลงมา
ซึ่งเมื่อ connection ขาดจากการกด Stop ตัว interpreter ก็ไม่ได้มองว่าเป็น exception แต่อย่างใด
ปล. หรือว่าผมเขียน PHP5 ไม่ถูกต้อง หรือไม่อย่างไร ... พอดีไม่เคยเขียนแบบ try-catch เลย เคยเขียนบ้างใน jsp และ code ตัวอย่างนี้ยึดตาม syntax แบบ jsp ถ้ายังงัย รบกวนผู้รู้แถลงด้วยน้ะครับ
รูปแบบ try catch ก็ดูปกติดีนะครับ
ผมยังไม่ได้เคยอ่านรายละเอียดเรื่อง exception ใน php เลยตั้งแต่เขาแนะนำเมื่อ version 5
ออกมา หลังจากเห็น code แล้ว ที่สงสัยก็คือ
exception จะเกิดได้อย่างไร ในเมื่อ method เดิมนั้น fput, fget ไม่ได้บอกไว้เลยว่า
เมื่อ call method นี้แล้ว จะมีโอกาสเกิด exception ชนิดใหนได้บ้าง
อันนี้งงมาก ก็เลยสงสัยว่า php จัดการ exception อย่างไร โดยเฉพาะเรื่องที่จะ handle existing functions
มันจะรับได้เฉพาะเมื่อมีการสั่ง throw exception ออกมาเองหรือเปล่า?
เอาเป็นว่า ผมรอฟังคำตอบจากโรตี มีชัย ดีกว่า :)
Surachai Tepkhumdee
ผมก็งูๆ ปลาๆ เกี่ยวกับ OO ของ php5 คงต้องพึ่งคุณ pomcob แล้วหล่ะครับ :)
ปล. ผมหล่ะข้องใจมาตลอดว่า คำว่า 'pomcob' นี่มันมีที่มา มาจากอะไรว่ะ??