>  기사  >  백엔드 개발  >  대용량 파일을 안전하게 다운로드하기 위한 PHP 구현 코드

대용량 파일을 안전하게 다운로드하기 위한 PHP 구현 코드

WBOY
WBOY원래의
2016-07-25 08:58:51812검색
  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-streamn" ); //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" . "nn" );
  25. } else {
  26. header ( "Content-Length:" . $filesize . "nn" );
  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으로 문의하세요.