1 /** 2 * @description 文件下载 支持本地和远程文件 3 * @param $fileUrl 本地文件绝对路径 OR 远程文件地址 4 * @param string $fileName 下载保存的文件名 5 */ 6 function download_file($fileUrl, $fileName = ''){ 7 if($fileName == ''){ 8 $filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $fileUrl)); 9 $filename = end($filename); 10 }else{ 11 $filename = $fileName; 12 } 13 //直接下载本地文件 14 if (!headers_sent()) { 15 if (file_exists($fileUrl) && !empty($filename)) { 16 $fileOpen = fopen($fileUrl, 'rb'); 17 $fileSize = filesize($fileUrl); 18 header("Cache-Control: public");//缓存控制 19 header("Content-Type: application/octet-stream"); 20 header("Accept-Ranges: bytes"); 21 header("Content-Length: " . $fileSize); 22 header('Access-Control-Expose-Headers: Content-Disposition'); 23 header("Content-Disposition: attachment; filename=" . $filename); 24 $chunk_size = 4096; // 针对大文件,规定每次读取文件的字节数为4096字节,直接输出数据 25 $sum_buffer = 0; //总的缓冲的字节数 26 ob_start(); // 开启缓冲区 27 //只要没到文件尾,就一直读取 28 while (!feof($fileOpen) && $sum_buffer < $fileSize) { 29 echo fread($fileOpen, $chunk_size); 30 $sum_buffer += $chunk_size; 31 ob_flush(); // 刷新PHP缓冲区到Web服务器 32 flush(); // 刷新Web服务器缓冲区到浏览器 33 } 34 ob_end_clean(); // 关闭缓冲区 35 fclose($fileOpen); 36 exit; 37 } 38 }else{ 39 exit; 40 } 41 //下载远程文件到本地 42 $localTemporaryDir = FILE_UPLOAD.'uploads/temporary/';//此处注意改成自己项目配置的文件下载目录 43 if(!is_dir($localTemporaryDir)){ 44 mkdir($localTemporaryDir,0777,true); 45 } 46 $localFile = $localTemporaryDir . $fileName; 47 $ch = curl_init(); 48 curl_setopt($ch, CURLOPT_URL, $url); 49 curl_setopt($ch, CURLOPT_HEADER, FALSE); 50 curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 51 curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 900); 52 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); 53 curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); 54 curl_setopt($ch, CURLOPT_BINARYTRANSFER, TRUE); 55 $file = curl_exec($ch); 56 curl_close($ch); 57 if(!strpos($file, '<Error>')){ 58 @unlink($localFile); 59 file_put_contents($localFile, $file); 60 } 61 if (file_exists($localFile)) { 62 download_file($localFile);//调用自己 63 } 64 }