Upload
thomas-weinert
View
3.646
Download
1
Tags:
Embed Size (px)
Citation preview
Deliver Files With PHP
Thomas Weinert
Thomas Weinert, papaya Software GmbH
About me
Application Developer▹ PHP
▹ XSLT/XPath
▹ (some) Javascript papaya CMS
▹ PHP based Content Management System
▹ uses XSLT for Templates
Thomas Weinert, papaya Software GmbH
Steps
Block Check
▹ Filename
▹ File Tell
▹ Date
▹ Size
▹ Type
▹ Name
Send▹ At Once
▹ Piece By Piece
▹ Limit Optimize
▹ Traffic
▹ Performance
▹ Flash Problems
Thomas Weinert, papaya Software GmbH
Block
Move outside document root
.htaccess▹ Deny From All
Rewrite?
Thomas Weinert, papaya Software GmbH
Check Filename
dirname(), basename() preg_match strrpos() + substr()
against database▹ Use hashed random strings for id
▹ Split at chars
▹ virtual directory structure
Thomas Weinert, papaya Software GmbH
Check File
file_exists()▹ return true for directories
is_file() is_readable()
Thomas Weinert, papaya Software GmbH
Check File Type
getimagesize() (no GD needed) /usr/bin/file ext/fileinfo (PHP 5.3)
Thomas Weinert, papaya Software GmbH
Tell Date
Last change
header('Last-modified: '. gmdate('D, d M Y H:i:s', $fileDate.' GMT');
header('Expires: '. gmdate('D, d M Y H:i:s', $expireTime).' GMT');
Valid until
Thomas Weinert, papaya Software GmbH
Tell Size
Size▹ Show progress in browser
header('Content-length: '.$fileSize);
Thomas Weinert, papaya Software GmbH
Tell Type
File Mime Type
Rewrite Filenames▹ IE check filename
header('Content-type: '.$mimeType);
Thomas Weinert, papaya Software GmbH
Force Download
IE and Opera
header('Content-type: application/octetstream');
header('Content-type: application/octet-stream');
Others
Thomas Weinert, papaya Software GmbH
Tell Filename
For files in browser or IE
header('Content-disposition: inline; filename="'. $data['file_name'].'"');
header('Content-disposition: attachment; filename="'. $data['file_name'].'"');
For downloads - except IE
Escape “ and \ in filename with \
Thomas Weinert, papaya Software GmbH
Send – At Once
fpassthru() readfile()
Pro:▹ Easy
Contra:▹ Less control
Thomas Weinert, papaya Software GmbH
Send - Piece By Piece
fread() fseek() echo, print() flush()
Thomas Weinert, papaya Software GmbH
Send – Piece By Piece
<?php if ($fh = fopen($localFileName, 'r')) { while (!feof($fh) && connection_status() == 0) { echo fread($fh, $bytesPerStep); flush(); } fclose($fh);}?>
Thomas Weinert, papaya Software GmbH
Send – Piece By Piece
<?php if ($fh = fopen($localFileName, 'r')) { //seek file to start position if ($fileOffset > 0) { fseek($fh, $fileOffset); } while (!feof($fh) && connection_status() == 0) { echo fread($fh, $bytesPerStep); flush(); } fclose($fh);}?>
Thomas Weinert, papaya Software GmbH
Optimize - Traffic
Range-Header▹ Send:
▪ header('Accept-Ranges: bytes');▹ Receive:
▪ $_SERVER['HTTP_RANGE']▪ bytes=[start1][]-[stop1][,start2][-][stop2][...]:
▹ Send:▪ header('Accept-Ranges: bytes');▪ header('HTTP/1.1 206 Partial Content');▪ header(sprintf('Content-Range: bytes %d-%d/%d', ...);
Thomas Weinert, papaya Software GmbH
Send – Bandwidth Limit
Track time and send bytes Sleep some time if sent to fast
▹ usleep(), sleep() Send first bytes without limit
Why? ▹ Video-Streaming
▹ User don't need all data
Thomas Weinert, papaya Software GmbH
if ($shapeRequest) { $bytesSend += $bytesPerStep; if ($bytesSend > $shapeLimitStart) { $timeDiff = microtime(TRUE) - $timeStart; $rate = ($bytesSend - $shapeLimitStart) / $timeDiff; if ($rate > $shapeLimitRate) { $sleepFunction($sleepTime); } }}
Thomas Weinert, papaya Software GmbH
Optimize - Performance
Close Sessions▹ session_write_close()
X-Sendfile▹ header('X-Sendfile: '.$localFileName);
▹ Header for Lighttpd
▹ Apache Extension
Thomas Weinert, papaya Software GmbH
Optimize – Flash I
Byte offset tables in video file▹ ffmpeg ... -g 500 ...
Special player sends GET parameter▹ JW FLV Player
Server checks GET parameter▹ PHP script
▹ Lighttpd module
Thomas Weinert, papaya Software GmbH
Optimize – Flash – Meta Data
Thomas Weinert, papaya Software GmbH
Optimize – Flash II
Check for GET parameters▹ start, pos, position
Output magic bytes▹ $flashHeader = 'FLV'.pack('CCNN', 1, 5, 9, 0);▹ 01 (version) 05 (audio and video)
00 00 00 09 (header size) 00 00 00 00 (size of previous tag)
Seek file Output file
Thomas Weinert, papaya Software GmbH
Problems
will disable flush() / cause buffering▹ ob_start()
▹ session.use_trans_sid
▹ zlib.output_compression
▹ http:/www.php.net/flush (Comments)
Adobe Acrobat Reader in IE has buggy Range headers support
Thomas Weinert, papaya Software GmbH
Links
X-Sendfile▹ http://blog.lighttpd.net/articles/2006/07/02/x-
sendfile
▹ http://tn123.ath.cx/mod_xsendfile/
Flash▹ http://www.jeroenwijering.com/
▹ http://ffmpeg.mplayerhq.hu/
▹
http://www.abasketfulofpapayas.de/