Deliver Files With PHP
Thomas Weinert
About me
   Application Developer
     ▹   PHP
     ▹   XSLT/XPath
     ▹   (some) Javascript

    papaya CMS
     ▹   P...
Steps
   Block                                 Send
   Check                                  ▹   At Once
     ▹   File...
Block
   Move outside document root


    .htaccess
     ▹   Deny From All

    Rewrite?




Thomas Weinert, papaya Sof...
Check Filename
   dirname(), basename()
   preg_match

    strrpos() + substr()


    against database
     ▹   Use ha...
Check File
   file_exists()
     ▹   return true for directories

    is_file()

    is_readable()




Thomas Weinert, ...
Check File Type
   getimagesize() (no GD needed)
   /usr/bin/file

    ext/fileinfo (PHP 5.3)




Thomas Weinert, papay...
Tell Date
   Last change

    header('Last-modified: '.
      gmdate('D, d M Y H:i:s', $fileDate.' GMT');



    Valid u...
Tell Size
   Size
     ▹   Show progress in browser


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




Thomas Weinert, ...
Tell Type
   File Mime Type

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




    Rewrite Filenames
     ▹   IE check ...
Force Download
    IE and Opera

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


 
     Others

 header('Content-...
Tell Filename
    For files in browser or IE

 header('Content-disposition: inline; filename=quot;'.
   $data['file_name'...
Send – At Once
   fpassthru()
   readfile()


    Pro:
     ▹    Easy

    Contra:
     ▹   Less control

Thomas Weine...
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() ...
Send – Piece By Piece
<?php
if ($fh = fopen($localFileName, 'r')) {
   //seek file to start position
   if ($fileOffset > ...
Optimize - Traffic
   Range-Header
     ▹   Send:
          ▪   header('Accept-Ranges: bytes');
     ▹   Receive:
       ...
Send – Bandwidth Limit
   Track time and send bytes
   Sleep some time if sent to fast
     ▹   usleep(), sleep()

    ...
if ($shapeRequest) {
  $bytesSend += $bytesPerStep;
  if ($bytesSend > $shapeLimitStart) {
    $timeDiff = microtime(TRUE)...
Optimize - Performance
   Close Sessions
     ▹   session_write_close()


   X-Sendfile
     ▹   header('X-Sendfile: '.$...
Optimize – Flash I
   Byte offset tables in video file
     ▹   ffmpeg ... -g 500 ...

    Special player sends GET para...
Optimize – Flash – Meta Data




Thomas Weinert, papaya Software GmbH
Optimize – Flash II
   Check for GET parameters
     ▹   start, pos, position

    Output magic bytes
     ▹   $flashHea...
Problems
   will disable flush() / cause buffering
     ▹   ob_start()
     ▹   session.use_trans_sid
     ▹   zlib.outpu...
Links
   X-Sendfile
     ▹   http://blog.lighttpd.net/articles/2006/07/02/x-
         sendfile
     ▹   http://tn123.ath....
Upcoming SlideShare
Loading in...5
×

Deliver Files With PHP

3,826
-1

Published on

Published in: Technology
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
3,826
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
29
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Deliver Files With PHP

  1. 1. Deliver Files With PHP Thomas Weinert
  2. 2. 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
  3. 3. Steps  Block  Send  Check ▹ At Once ▹ Filename ▹ Piece By Piece ▹ File ▹ Limit  Tell  Optimize ▹ Date ▹ Traffic ▹ Size ▹ Performance ▹ Type ▹ Flash ▹ Name Thomas Weinert, papaya Software GmbH  Problems
  4. 4. Block  Move outside document root  .htaccess ▹ Deny From All  Rewrite? Thomas Weinert, papaya Software GmbH
  5. 5. 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
  6. 6. Check File  file_exists() ▹ return true for directories  is_file()  is_readable() Thomas Weinert, papaya Software GmbH
  7. 7. Check File Type  getimagesize() (no GD needed)  /usr/bin/file  ext/fileinfo (PHP 5.3) Thomas Weinert, papaya Software GmbH
  8. 8. Tell Date  Last change header('Last-modified: '. gmdate('D, d M Y H:i:s', $fileDate.' GMT');  Valid until header('Expires: '. gmdate('D, d M Y H:i:s', $expireTime).' GMT'); Thomas Weinert, papaya Software GmbH
  9. 9. Tell Size  Size ▹ Show progress in browser header('Content-length: '.$fileSize); Thomas Weinert, papaya Software GmbH
  10. 10. Tell Type  File Mime Type header('Content-type: '.$mimeType);  Rewrite Filenames ▹ IE check filename Thomas Weinert, papaya Software GmbH
  11. 11. Force Download  IE and Opera header('Content-type: application/octetstream');  Others header('Content-type: application/octet-stream'); Thomas Weinert, papaya Software GmbH
  12. 12. Tell Filename  For files in browser or IE header('Content-disposition: inline; filename=quot;'. $data['file_name'].'quot;');  For downloads - except IE header('Content-disposition: attachment; filename=quot;'. $data['file_name'].'quot;');  Escape “ and in filename with Thomas Weinert, papaya Software GmbH
  13. 13. Send – At Once  fpassthru()  readfile()  Pro: ▹ Easy  Contra: ▹ Less control Thomas Weinert, papaya Software GmbH
  14. 14. Send - Piece By Piece  fread()  fseek()  echo, print()  flush() Thomas Weinert, papaya Software GmbH
  15. 15. 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
  16. 16. 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); } ?> Weinert, papaya Software GmbH Thomas
  17. 17. 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
  18. 18. 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
  19. 19. 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
  20. 20. Optimize - Performance  Close Sessions ▹ session_write_close()  X-Sendfile ▹ header('X-Sendfile: '.$localFileName); ▹ Header for Lighttpd ▹ Apache Extension Thomas Weinert, papaya Software GmbH
  21. 21. 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
  22. 22. Optimize – Flash – Meta Data Thomas Weinert, papaya Software GmbH
  23. 23. 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
  24. 24. 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
  25. 25. 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/ ▹ Thomas Weinert, papaya Software GmbH  http://www.abasketfulofpapayas.de/
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×