Heim  >  Artikel  >  Backend-Entwicklung  >  php安全下载大文件的实现代码

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

WBOY
WBOYOriginal
2016-07-25 08:58:51778Durchsuche
  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);
复制代码


Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn