![]() หมวดหมู่
|
ส่งไฟล์ออกจาก PHP แบบบีบอัดข้อมูลด้วย Zip
วันที่
14 ต.ค. 51 + 03:51.45
ความคิดเห็น
0
กลุ่ม
PHP
มาเข้า เรื่องกันเลยคับ การจะสร้างการบีบอัดข้อมูล เราก็ตั้งเป็น Zip Library ซะก่อน ไปเปิดซะใน Extention ของ PHP แก้ไขที่ Config ของ PHP (php.ini) การแก้เปิดก็คือเอา ; ที่อยู่ด้านหน้าของ php_zip.dll ออก ถ้าเป็นของ Windiows นะคับ ถ้าเป็นของ UNIX นี่ไม่รู้ว่าเป็นอะไร คงจะเป็น php_zip.h ล่ะมั้ง
วิธีการ บีบอัดข้อมูลนี้ ผมได้ศึกษาจากคำสั่งของ phpMyAdmin นะคับ เนื่องจากอยากจะอลงให้ประสิทธิภาพของ Server ให้ครบหน่อย เพราะพอดี Server ที่ผมเช่าทำเวปอยู่นี้เค้าเปิดให้ใช้ Library นี้พอดี หึหึ ต้องดูก่อนว่าผมจะประยุกษ์เอามาใช้งานอะไรได้มั่ง ที่รู้จะถูกบรรจุอยู่ในโปรแกรม U-Forum !! ในรุ่นต่อๆ ไปคับ การจะ บีบอัดนี้ ในคำสั่งที่ผมแกะๆ มา รู้สึกจะเป็นการเขียนโปรแกรมแบบ OOP คือการเขียนโปรแกรมเชิงวัตถุอ่ะคับ มีการสร้าง Class สร้างนู่น สร้างนี่ ขั้นแรกเราตั้งสร้างไฟล์ Class ของคำสั่ง Zip นี่ซะก่อน โดย คำสั่งของไฟล์ Class นี้อู่ด้านล่างนี้นะคับ ซึ่งเป็น Zip Class จากโปรแกรม phpMyAdmin เห็นเค้าเขียนบอกว่าเป็นเวอร์ชั่น 1.7 จากโปรแกรม phpMyAdmin ver.2.4.0 RC-1 ซึ่งผมมาลองตรวจสอบดูแล้วพบว่า ไอ้เวอร์ชั่น 1.6 กะ 1.7 มันไม่ได้แตกต่างกันแม้แต่นิดเดียวเลย ถ้าไม่นับตัวเลขบ่งบอกเวอร์ชั่น (รึผมมีตาหามีแววไม่กัน) แต่ที่เอามาให้ดูผมได้ย่อคำสั่งแล้ว โดยการตัด Comment ออก ใครอยากได้ Comment ที่ตัดออกก็ไปหาเอาที่ phpMyAdmin เอานะคับ <?
class zipfile
{
var $datasec = array();
var $ctrl_dir = array();
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
var $old_offset = 0;
function unix2DosTime($unixtime = 0)
{
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
if($timearray['year'] < 1980)
{
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
}
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
}
function addFile($data, $name, $time = 0)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix2DosTime($time));
$hexdtime = '\x' . $dtime[6] . $dtime[7] . '\x' . $dtime[4] . $dtime[5] . '\x' . $dtime[2] . $dtime[3] . '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$fr = "\x50\x4b\x03\x04\x14\x00\x00\x00\x08\x00" . $hexdtime;
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2);
$c_len = strlen($zdata);
$fr .= pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len) . pack('v', strlen($name)) . pack('v', 0) . $name . $zdata . pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len);
$this -> datasec[] = $fr;
$new_offset = strlen(implode('', $this->datasec));
$cdrec = "\x50\x4b\x01\x02\x00\x00\x14\x00\x00\x00\x08\x00" . $hexdtime . pack('V', $crc) . pack('V', $c_len) . pack('V', $unc_len) . pack('v', strlen($name)) . pack('v', 0 ) . pack('v', 0 ) . pack('v', 0 ) . pack('v', 0 ) . pack('V', 32 ) . pack('V', $this -> old_offset );
$this -> old_offset = $new_offset;
$cdrec .= $name;
$this -> ctrl_dir[] = $cdrec;
}
function file()
{
$data = implode('', $this -> datasec);
$ctrldir = implode('', $this -> ctrl_dir);
return $data . $ctrldir . $this -> eof_ctrl_dir . pack('v', sizeof($this -> ctrl_dir)) . pack('v', sizeof($this -> ctrl_dir)) . pack('V', strlen($ctrldir)) . pack('V', strlen($data)) . "\x00\x00";
}
}
?>นี่แหล่ะคับคำสั่งของการสร้างการบีบอัดข้อมูล ซึ่งผมได้ย่อคำสั่งลงมาคับ จะเห็นว่าในนี้มันได้เตรียมของทุกอย่างไว้ให้แล้ว ทั้งการบีบอัด ชื่อไฟล์ วันที่ เหลือแต่ผมไม่รู้ว่ามันสร้างไฟล์บีบอัดแบบดันใน Zip มีอยู่หลายไฟล์ได้หรือเปล่า อันนี้เด๋วขอกลับไปนั่งลองของก่อนอ่ะคับ เอาล่ะ จะมาพูดถึงขั้นตอนการบีบอัดเลยนะคับ ในที่นี้ผมผมจะพูดถึงของ Zip เท่านั้นนะคับ เพราะผมไม่ของให้ลองแค่บน Windows เท่านั้น พยายามจะไปหา Linux TLE 5 มาลงอยู่ แต่จนปัญญาจริงๆ ไม่มีร้านไหนขายซักร้าน ผมก็ไม่ รู้จะอธิบายยังไงดี เอาเป็นว่าจะขออธิบายเป็น Source Code ก็แล้วกันนะคับ ดูถ้าจะรู้เรื่องกว่า เพราะนึกไม่ออกว่าจะอธิบายยังไงอย่างไรดี เอาเป็ว่าเรามีไฟล์อยู่ไฟล์นหนึ่งชื่อว่า data.txt เป็น Text ไฟล์ (บอกทำไมดูนามสกุลก็น่าจะรู้อยู่แล้ว) เราจะเรียกไฟล์นี้เข้ามาบีบอัด แล้วส่งออกไปเป็นไฟล์ให้ดาวน์โหลดนะคับ มาดูขั้นตอนการทำดู เราจะมีไฟล์ทั้งหมด 4 ไฟล์นะคับ คือ zip.html : เป็นไฟล์ HTML ธรรมดา ที่ในนั้นจะมี Hyper Link ไว้สำหรับคลิ้กเข้าไปที่หน้าประมวลผล เพพราะผมลองรันโปรแกรมจะหน้าประมวลผลเลยไม่ได้คับ มันจะไม่ส่งไฟล์ออกมา แต่จะส่งออกมาที่หน้าเวปแทน เป็นตัวอักษรขอมอะไรก็ไม่รู้ zip.php : เป็นไฟล์ประมวลผลของมูลคับ สำหรับรวมคำสั่งการบีบอัดข้อมูล zip.lib.php : เป็นไฟล์ Library ของ ZIP Class จะรวม Class ของ คำสั่ง Zip ไว้ เป็นการเขียนโปรแกรมเชิงวัตถุ ส่วน Source Code ของไฟล์นี้ก็อยู่ด้านบนอ่ะคับ ดูเอาเอง data.txt : เป็นไฟล์ข้อมูล ที่เราต้องการจะบีบอัดแล้วส่งออกมาให้ดาวน์โหลด ในที่ นี้ผมจะนำเสนอ Source Code ของไฟล์ zip.lib.php ซึ่งนำเสนอให้เห็นไปแล้วก็ไฟล์ zip.php เท่านั้น ส่วนไฟล์ zip.html นั้นภายในก็ไม่มีอะไรมาก ก็แค่สร้างลิงค์ไปที่ไฟล์ zip.php เท่านั้น ส่วนไฟล์ data.txt ก็เป็นแค่ไฟล์ข้อมูล จะเอาไฟล์อะไรมาทำก็ได้อ่ะคับ เอาล่ะมาลองดู Source Code ของไฟล์ zip.php กันนะคับ จะอธิบายให้เข้าใจมากที่สุดนะคับ <?
require('./zip.lib.php');
/* กำหนดชื่อไฟล์ที่ต้องการบีบอัด โดยไม่เขียนนามสกุล */
$data_file = 'data';
/* นามสกุลของไฟล์ที่ต้องการจะบีบอัด */
$ext = 'txt';
/* ชนิดของไฟล์ที่ต้องการส่งออก ในที่นี้คือ Zip FIle ก็ต้องกำหนดเป็น application/x-zip */
$mime_type = 'application/x-zip';
/* วันเวลาที่ทำการสร้างไฟล์บีบอัด */
$now = gmdate('D, d M Y H:i:s') . ' GMT';
/* ดึงข้อมูลในไฟล์ทั้งหมดเก็บลงตัวแปล */
$dump_buffer = file_get_content($data_file.'.'.$ext);
/* เรียก Class zipfile ขึ้นมา */
$zipfile = new zipfile();
$zipfile -> addFile($dump_buffer, $data_file.'.'.$ext);
/* ทำการบีบอัดข้อมูลโดยใช้เมธอดภายใน Class zipfile แล้วคืนค่าออกมาที่ตัวแปล $dump_buffer */
$dump_buffer = $zipfile -> file();
/* กำหนดชนิดดข้อมูลที่ต้องการส่งออก */
header('Content-Type: ' . $mime_type);
header('Expires: ' . $now);
/* ตรวจสอบว่าผู้ที่เปิดไฟล์นี้ใช้ IE เปิดหรือไม่ ถ้าใช่ก็ส่ง header อีกแบบไป ถ้าไม่ใช่ก็ส่งไปอีกแบบ รู้ก็รู้ว่า Microsoft ทำอะไรไม่เหมือนชาวบ้านอ่ะ */
if(ereg('MSIE ([0-9].[0-9]{1,2})', $HTTP_USER_AGENT)){
header('Content-Disposition: inline; filename="'.$data_file.'.zip"');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
}
else
{
header('Content-Disposition: attachment; filename="'.$data_file.'.zip"');
header('Pragma: no-cache');
}
/* ขั้นสุดท้ายก็แสดงผลข้อมูลที่บีบอัดออกมา */
echo $dump_buffer;
?>จบแล้ว ครับบทความนี้ ไม่รู้ว่าจะสงสัยอะไรหรือไม่ ก็ลองๆ ทำตามดู แต่ขอย้ำว่า php_zip.dll ต้องเปิดเอาไว้นะคับ บางคนอาจสงสัยว่าใช้คำสั่ง echo แสดงผลข้อมูล มันจะไม่พิมพ์ออกมาทางหน้าเวปหรือ อันนี้ตอบได้คับ คือเรากำหนด header แล้วว่าข้อมูลที่ส่งออกไปจะเป็นแบบ zip น้า เมื่อบอกไปแล้วทาง Browser ก็รู้แล้วว่าควรจะรับข้อมูลแบบใด ถ้าเป็นแบบ html มันก็จะรับแล้วแสดงผลที่หน้าเวปไงอ่ะคับ ถ้าเป็นแบบ zip มันก็จะเปิดหน้าต่าง Download ขึ้นมาให้บันทึกลงเครื่องเราคับ
|
ขับเคลื่อนโดย un-no Engine 2.1.2 © ลิขสิทธ์โดย บริษัท อันโน คอร์ปอเรชั่น จำกัด [ แผนที่เว็บไซต์ ]
แก้ไขล่าสุด: 2009-11-15 00:40:43, หมายเลขเซสชั่น: ce3dd4e452b40e0dc877041c2c00c3db, ใช้เวลาสร้าง: 0.019927025 วินาที