25
Deliver Files With PHP Thomas Weinert

Deliver Files With PHP

Embed Size (px)

Citation preview

Page 1: Deliver Files With PHP

Deliver Files With PHP

Thomas Weinert

Page 2: Deliver Files With PHP

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

Page 3: Deliver Files With PHP

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

Page 4: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Block

Move outside document root

.htaccess▹ Deny From All

Rewrite?

Page 5: Deliver Files With PHP

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

Page 6: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Check File

file_exists()▹ return true for directories

is_file() is_readable()

Page 7: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Check File Type

getimagesize() (no GD needed) /usr/bin/file ext/fileinfo (PHP 5.3)

Page 8: Deliver Files With PHP

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

Page 9: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Tell Size

Size▹ Show progress in browser

header('Content-length: '.$fileSize);

Page 10: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Tell Type

File Mime Type

Rewrite Filenames▹ IE check filename

header('Content-type: '.$mimeType);

Page 11: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Force Download

IE and Opera

header('Content-type: application/octetstream');

header('Content-type: application/octet-stream');

Others

Page 12: Deliver Files With PHP

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 \

Page 13: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Send – At Once

fpassthru() readfile()

Pro:▹ Easy

Contra:▹ Less control

Page 14: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Send - Piece By Piece

fread() fseek() echo, print() flush()

Page 15: Deliver Files With PHP

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);}?>

Page 16: Deliver Files With PHP

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);}?>

Page 17: Deliver Files With PHP

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', ...);

Page 18: Deliver Files With PHP

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

Page 19: Deliver Files With PHP

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); } }}

Page 20: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Optimize - Performance

Close Sessions▹ session_write_close()

X-Sendfile▹ header('X-Sendfile: '.$localFileName);

▹ Header for Lighttpd

▹ Apache Extension

Page 21: Deliver Files With PHP

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

Page 22: Deliver Files With PHP

Thomas Weinert, papaya Software GmbH

Optimize – Flash – Meta Data

Page 23: Deliver Files With PHP

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

Page 24: Deliver Files With PHP

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

Page 25: Deliver Files With PHP

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/