首页  >  文章  >  后端开发  >  php安全下载大文件的实现代码

php安全下载大文件的实现代码

WBOY
WBOY原创
2016-07-25 08:58:51810浏览
  1. /**
  2. * 一般文件安全下载
  3. * edit bbs.it-home.org
  4. */
  5. $durl = 'file/phpcms2008_o2abf32efj883c91a.iso';
  6. $filename = 'phpcms2008_o2abf32efj883c91a.iso';
  7. $file = @fopen($durl, 'r');
  8. header("Content-Type: application/octet-stream");
  9. header("Accept-Ranges: bytes");
  10. header("Accept-Length: ".filesize($durl));
  11. header("Content-Disposition: attachment; filename=".$filename);
  12. echo fread($file,filesize($durl));
  13. fclose($file);
  14. ?>
复制代码

以上的代码,在遇到大文件时,超过php.ini配置的内存最大值的文件时,服务器会非常占用CPU资源,文件不能正常下载,只能下载几十Kb的文件。 可以用下面的代码来解决:

  1. /**
  2. * 大文件安全下载的实现代码
  3. * edit bbs.it-home.org
  4. */
  5. function download($url, $filename) {
  6. // 获得文件大小, 防止超过2G的文件, 用sprintf来读
  7. $filesize = sprintf ( "%u", filesize ( $url ) );
  8. if (! $filesize) {
  9. return;
  10. }
  11. header ( "Content-type:application/octet-stream\n" ); //application/octet-stream
  12. header ( "Content-type:unknown/unknown;" );
  13. header ( "Content-disposition: attachment; filename=\"" . $filename . "\"" );
  14. header ( 'Content-transfer-encoding: binary' );
  15. if ($range = getenv ( 'HTTP_RANGE' )) { // 当有偏移量的时候,采用206的断点续传头
  16. $range = explode ( '=', $range );
  17. $range = $range [1];
  18. header ( "HTTP/1.1 206 Partial Content" );
  19. header ( "Date: " . gmdate ( "D, d M Y H:i:s" ) . " GMT" );
  20. header ( "Last-Modified: " . gmdate ( "D, d M Y H:i:s", filemtime ( $url ) ) . " GMT" );
  21. header ( "Accept-Ranges: bytes" );
  22. header ( "Content-Length:" . ($filesize - $range) );
  23. header ( "Content-Range: bytes " . $range . ($filesize - 1) . "/" . $filesize );
  24. header ( "Connection: close" . "\n\n" );
  25. } else {
  26. header ( "Content-Length:" . $filesize . "\n\n" );
  27. $range = 0;
  28. }
  29. loadFile ( $url );
  30. }
  31. function loadFile($filename, $retbytes = true) {
  32. $buffer = '';
  33. $cnt = 0;
  34. $handle = fopen ( $filename, 'rb' );
  35. if ($handle === false) {
  36. return false;
  37. }
  38. while ( ! feof ( $handle ) ) {
  39. $buffer = fread ( $handle, 1024 * 1024 );
  40. echo $buffer;
  41. ob_flush ();
  42. flush ();
  43. if ($retbytes) {
  44. $cnt += strlen ( $buffer );
  45. }
  46. }
  47. $status = fclose ( $handle );
  48. if ($retbytes && $status) {
  49. return $cnt; // return num. bytes delivered like readfile() does.
  50. }
  51. return $status;
  52. }
  53. ?>
复制代码

调用示例:

  1. //大文件的安全下载
  2. download($url, $filename);
复制代码


声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn