合规国际互联网加速 OSASE为企业客户提供高速稳定SD-WAN国际加速解决方案。 广告
<ul> <li><a href="download.php?id=1">文件1</a></li> <li><a href="download.php?id=2">文件2</a></li> <li><a href="download.php?id=3">文件3</a></li> </ul> ``` <ul> <li><a href="download.php?id=1">文件1</a></li> <li><a href="download.php?id=2">文件2</a></li> <li><a href="download.php?id=3">文件3</a></li> </ul> ``` php: ``` //通过这个id去获取数据库下载表中的下载路径,然后把下载路径放入下面代码中打开... $id = GET['id']; //打开文件 $file = fopen('test.rar','r'); //定义下载头部信息 header("content-type:application/octet-stream"); header("accept-ranges:bytes"); //清理filesize()函数的缓存 clearstatcache(); header("accept-length:".filesize('test.rar')); header("content-disposition:attachement;filename='test.rar'"); echo fread($file,filesize('test.rar')); fclose($file); exit; ``` 完整代码 ``` /*下载*/ public function download() { $id=Request::get('id/d'); $data=_CURRENT_MODEL::getDataById($id); $publicPath=app()->getRootPath().DIRECTORY_SEPARATOR.'public'; $filepath=$data['files']; //打开文件 try { $file= $publicPath.$filepath; $fiename=$data['title'].'.'.pathinfo($file)['extension']; // halt($file); $file_resource = fopen($file,'r'); //定义下载头部信息 header("content-type:application/octet-stream"); header("accept-ranges:bytes"); //清理filesize()函数的缓存 clearstatcache(); header("accept-length:".filesize($file)); header("content-disposition:attachement;filename={$fiename}"); echo fread($file_resource,filesize($file)); fclose($file_resource); } catch (\Exception $e) { errorLog($e); exit('文件不存在!'); } $res=_CURRENT_MODEL::downloadNumInc($id); // dump($res); exit; } ``` [tp_software_material_record](javascript:;) 上面的download函数无法下载大文件 用下面的sendFile替换上面的download函数 ``` /** * 下载文件 * * @author: legend(legendsky@hotmail.com) * @link: http://www.ugia.cn/?p=109 * @description: send file to client * @version: 1.0 * * @param string $fileName 文件名称或路径 * @param string $fancyName 自定义的文件名,为空则使用filename * @param boolean $forceDownload 是否强制下载 * @param integer $speedLimit 速度限制,单位为字节,0为不限制,不支持windows服务器 * @param string $$contentType 文件类型,默认为application/octet-stream * * @return boolean */ function sendFile($fileName, $fancyName = '', $forceDownload = true, $speedLimit = 0, $contentType = '') { if (!is_readable($fileName)) { header("HTTP/1.1 404 Not Found"); return false; } $fileStat = stat($fileName); $lastModified = $fileStat['mtime']; $md5 = md5($fileStat['mtime'] .'='. $fileStat['ino'] .'='. $fileStat['size']); $etag = '"' . $md5 . '-' . crc32($md5) . '"'; header('Last-Modified: ' . gmdate("D, d M Y H:i:s", $lastModified) . ' GMT'); header("ETag: $etag"); if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lastModified) { header("HTTP/1.1 304 Not Modified"); return true; } if (isset($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_UNMODIFIED_SINCE']) < $lastModified) { header("HTTP/1.1 304 Not Modified"); return true; } if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag) { header("HTTP/1.1 304 Not Modified"); return true; } if ($fancyName == '') { $fancyName = basename($fileName); } if ($contentType == '') { $contentType = 'application/octet-stream'; } $fileSize = $fileStat['size']; $contentLength = $fileSize; $isPartial = false; if (isset($_SERVER['HTTP_RANGE'])) { if (preg_match('/^bytes=(d*)-(d*)$/', $_SERVER['HTTP_RANGE'], $matches)) { $startPos = $matches[1]; $endPos = $matches[2]; if ($startPos == '' && $endPos == '') { return false; } if ($startPos == '') { $startPos = $fileSize - $endPos; $endPos = $fileSize - 1; } else if ($endPos == '') { $endPos = $fileSize - 1; } $startPos = $startPos < 0 ? 0 : $startPos; $endPos = $endPos > $fileSize - 1 ? $fileSize - 1 : $endPos; $length = $endPos - $startPos + 1; if ($length < 0) { return false; } $contentLength = $length; $isPartial = true; } } // send headers if ($isPartial) { header('HTTP/1.1 206 Partial Content'); header("Content-Range: bytes $startPos-$endPos/$fileSize"); } else { header("HTTP/1.1 200 OK"); $startPos = 0; $endPos = $contentLength - 1; } header('Pragma: cache'); header('Cache-Control: public, must-revalidate, max-age=0'); header('Accept-Ranges: bytes'); header('Content-type: ' . $contentType); header('Content-Length: ' . $contentLength); if ($forceDownload) { header('Content-Disposition: attachment; filename="' . rawurlencode($fancyName). '"');//汉字自动转为URL编码 header('Content-Disposition: attachment; filename="' . $fancyName. '"'); } header("Content-Transfer-Encoding: binary"); $bufferSize = 2048; if ($speedLimit != 0) { $packetTime = floor($bufferSize * 1000000 / $speedLimit); } $bytesSent = 0; $fp = fopen($fileName, "rb"); fseek($fp, $startPos); //fpassthru($fp); while ($bytesSent < $contentLength && !feof($fp) && connection_status() == 0 ) { if ($speedLimit != 0) { list($usec, $sec) = explode(" ", microtime()); $outputTimeStart = ((float)$usec + (float)$sec); } $readBufferSize = $contentLength - $bytesSent < $bufferSize ? $contentLength - $bytesSent : $bufferSize; $buffer = fread($fp, $readBufferSize); echo $buffer; ob_flush(); flush(); $bytesSent += $readBufferSize; if ($speedLimit != 0) { list($usec, $sec) = explode(" ", microtime()); $outputTimeEnd = ((float)$usec + (float)$sec); $useTime = ((float) $outputTimeEnd - (float) $outputTimeStart) * 1000000; $sleepTime = round($packetTime - $useTime); if ($sleepTime > 0) { usleep($sleepTime); } } } return true; } ``` 封装的下载类,不仅可以下载大文件还可以断点续传 ``` <?php namespace dash; class FileDownload{ // class start private $_speed = 512; // 下载速度 /** 下载 * @param String $file 要下载的文件路径 * @param String $name 文件名称,为空则与下载的文件名称一样 * @param boolean $reload 是否开启断点续传 */ public function download($file, $name='', $reload=false){ if(file_exists($file)){ if($name==''){ $name = basename($file); } $fp = fopen($file, 'rb'); $file_size = filesize($file); $ranges = $this->getRange($file_size); header('cache-control:public'); header('content-type:application/octet-stream'); header('content-disposition:attachment; filename='.$name); if($reload && $ranges!=null){ // 使用续传 header('HTTP/1.1 206 Partial Content'); header('Accept-Ranges:bytes'); // 剩余长度 header(sprintf('content-length:%u',$ranges['end']-$ranges['start'])); // range信息 header(sprintf('content-range:bytes %s-%s/%s', $ranges['start'], $ranges['end'], $file_size)); // fp指针跳到断点位置 fseek($fp, sprintf('%u', $ranges['start'])); }else{ header('HTTP/1.1 200 OK'); header('content-length:'.$file_size); } while(!feof($fp)){ echo fread($fp, round($this->_speed*1024,0)); ob_flush(); //sleep(1); // 用于测试,减慢下载速度 } ($fp!=null) && fclose($fp); }else{ return ''; } } /** 设置下载速度 * @param int $speed */ public function setSpeed($speed){ if(is_numeric($speed) && $speed>16 && $speed<4096){ $this->_speed = $speed; } } /** 获取header range信息 * @param int $file_size 文件大小 * @return Array */ private function getRange($file_size){ if(isset($_SERVER['HTTP_RANGE']) && !empty($_SERVER['HTTP_RANGE'])){ $range = $_SERVER['HTTP_RANGE']; $range = preg_replace('/[\s|,].*/', '', $range); $range = explode('-', substr($range, 6)); if(count($range)<2){ $range[1] = $file_size; } $range = array_combine(array('start','end'), $range); if(empty($range['start'])){ $range['start'] = 0; } if(empty($range['end'])){ $range['end'] = $file_size; } return $range; } return null; } } // class end ```