-
- /**
- * 一般文件安全下载
- * edit bbs.it-home.org
- */
- $durl = 'file/phpcms2008_o2abf32efj883c91a.iso';
- $filename = 'phpcms2008_o2abf32efj883c91a.iso';
- $file = @fopen($durl, 'r');
- header("Content-Type: application/octet-stream");
- header("Accept-Ranges: bytes");
- header("Accept-Length: ".filesize($durl));
- header("Content-Disposition: attachment; filename=".$filename);
- echo fread($file,filesize($durl));
- fclose($file);
- ?>
复制代码
以上的代码,在遇到大文件时,超过php.ini配置的内存最大值的文件时,服务器会非常占用CPU资源,文件不能正常下载,只能下载几十Kb的文件。
可以用下面的代码来解决:
-
- /**
- * 大文件安全下载的实现代码
- * edit bbs.it-home.org
- */
- function download($url, $filename) {
- // 获得文件大小, 防止超过2G的文件, 用sprintf来读
- $filesize = sprintf ( "%u", filesize ( $url ) );
- if (! $filesize) {
- return;
- }
- header ( "Content-type:application/octet-streamn" ); //application/octet-stream
- header ( "Content-type:unknown/unknown;" );
- header ( "Content-disposition: attachment; filename="" . $filename . """ );
- header ( 'Content-transfer-encoding: binary' );
- if ($range = getenv ( 'HTTP_RANGE' )) { // 当有偏移量的时候,采用206的断点续传头
- $range = explode ( '=', $range );
- $range = $range [1];
-
- header ( "HTTP/1.1 206 Partial Content" );
- header ( "Date: " . gmdate ( "D, d M Y H:i:s" ) . " GMT" );
- header ( "Last-Modified: " . gmdate ( "D, d M Y H:i:s", filemtime ( $url ) ) . " GMT" );
- header ( "Accept-Ranges: bytes" );
- header ( "Content-Length:" . ($filesize - $range) );
- header ( "Content-Range: bytes " . $range . ($filesize - 1) . "/" . $filesize );
- header ( "Connection: close" . "nn" );
- } else {
- header ( "Content-Length:" . $filesize . "nn" );
- $range = 0;
- }
- loadFile ( $url );
- }
-
- function loadFile($filename, $retbytes = true) {
- $buffer = '';
- $cnt = 0;
- $handle = fopen ( $filename, 'rb' );
- if ($handle === false) {
- return false;
- }
- while ( ! feof ( $handle ) ) {
- $buffer = fread ( $handle, 1024 * 1024 );
- echo $buffer;
- ob_flush ();
- flush ();
- if ($retbytes) {
- $cnt = strlen ( $buffer );
- }
- }
- $status = fclose ( $handle );
- if ($retbytes && $status) {
- return $cnt; // return num. bytes delivered like readfile() does.
- }
- return $status;
- }
- ?>
复制代码
调用示例:
-
- //大文件的安全下载
- download($url, $filename);
复制代码
|