8月 5, 2022 - php开发 php通过url下载大文件已关闭评论
php通过url下载大文件
1:用户通过浏览器点击下载:
//文件url $filename = 'https://mpace-staging.oss-cn-shanghai.aliyuncs.com/seebats-demo/uJlWlEDEpF.mp4'; //文件大小 $filesize = Storage::size('seebats-demo/uJlWlEDEpF.mp4'); //设定header头为下载 header('content-type:application/octet-stream'); header('Accept-Ranges:bytes'); //相应大小 header('Accept-Length:'.$filesize); header('Content-Disposition:attachment;filename='.basename($filename)); //分片下载:每次:1024个byte=1kb $read_buffer = 1024; $sum_buffer = 0; $handle = fopen($filename, 'rb'); while (!feof($handle) && $sum_buffer < $filesize) { echo fread($handle, $read_buffer); $sum_buffer += $read_buffer; } fclose($handle);
2:下载到本地
//文件url $filename = 'https://mpace-staging.oss-cn-shanghai.aliyuncs.com/seebats-demo/uJlWlEDEpF.mp4'; //文件大小 $filesize = Storage::size('seebats-demo/uJlWlEDEpF.mp4'); //设定header头为下载 //header('content-type:application/octet-stream'); //header('Accept-Ranges:bytes'); //响应大小 //header('Accept-Length:'.$filesize); //header('Content-Disposition:attachment;filename='.basename($filename)); //分片下载:每次:1024个byte=1kb $read_buffer = 1024; $sum_buffer = 0; $content = ''; $handle = fopen($filename, 'rb'); while (!feof($handle) && $sum_buffer < $filesize) { $content .= fread($handle, $read_buffer); $sum_buffer += $read_buffer; } fclose($handle); $res = Storage::disk('local')->put('download.mp4', $content);
或者把每次的content直接写入文件(fwrite函数)
$read_buffer = 1024; $sum_buffer = 0; $save_to = storage_path().'/app/download.mp4'; $local_file = fopen($save_to, 'wb'); $handle = fopen($filename, 'rb'); while (!feof($handle) && $sum_buffer < $filesize) { $content = fread($handle, $read_buffer); fwrite($local_file, $content); $sum_buffer += $read_buffer; } fclose($handle);
3: 下载到本地:
class FileDownload { /** * 下载远程大文件 * * @param string $sourceFileUrl 远程文件地址 * @param string $targetFile 远程文件下载到本地的本地地址 * @param float|int $pieceSize 每次分片大小 M (默认100 因采用命令形式,不占用程序执行时内存) * @return bool */ public static function downloadLargeFile($sourceFileUrl, $targetFile, $pieceSize = 100) { $pieceSize = 1024 * 1024 * $pieceSize; $size = self::getRemoteFileSize($sourceFileUrl); if ($size === false) { return false; } $from = 0; $i = 0; $isSuccess = true; do { $to = min($from + $pieceSize - 1, $size); $partTargetFile = $targetFile . '_' . $i++; $partFiles[] = $partTargetFile; $r = self::downFileByPiece($sourceFileUrl, $partTargetFile, $from, $to); if ($r === false) { $isSuccess = false; break; } $from = $to + 1; if ($from > $size) { break; } } while(true); // 合并文件 if ($isSuccess) { $combineCmd = "cat " . implode(' ', $partFiles) . " > " . $targetFile; exec($combineCmd, $o, $ret); if ($ret != 0) { $isSuccess = false; } } // 清理临时文件 foreach ($partFiles as $partFile) { if (file_exists($partFile)) { @unlink($partFile); } } return $isSuccess; } /** * 分片下载远程文件 * * @param string $sourceFile 远程文件地址 * @param string $savePath 远程文件分片下载到本地的本地分片地址 * @param int $fromByte 远程文件分片起始位置 * @param int $toByte 远程文件分片结束位置(-1 表示直到文件结束) * @return bool */ private static function downFileByPiece($sourceFile, $savePath, $fromByte = 0, $toByte = -1) { if (file_exists($savePath)) { return true; } $cmd = "curl --range " . $fromByte . "-"; if ($toByte > 0) { $cmd .= $toByte; } $cmd .= " -o " . $savePath . " '" . $sourceFile . "'"; exec($cmd, $o, $ret); if ($ret != 0) { return false; } return true; } /** * 获取远程文件的大小 * * @param string $fileUrl 远程文件地址 * @return false|mixed */ private static function getRemoteFileSize($fileUrl) { $ch = curl_init(); curl_setopt($ch,CURLOPT_URL,$fileUrl); curl_setopt($ch, CURLOPT_HEADER, 1); curl_setopt($ch, CURLOPT_NOBODY, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); //忽略https if(strpos($fileUrl,'https')!==false){ curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); } $head = curl_exec($ch); curl_close($ch); $regex = '/Content-Length:\s([0-9].+?)\s/'; preg_match($regex, $head, $matches); if (isset($matches[1])) { return $matches[1]; } return false; } }
4:推荐使用:
/** | |
* Download helper to download files in chunks and save it. | |
* | |
* @author Syed I.R <syed@lukonet.com> | |
* @link https://github.com/irazasyed | |
* | |
* @param string $srcName Source Path/URL to the file you want to download | |
* @param string $dstName Destination Path to save your file | |
* @param integer $chunkSize (Optional) How many bytes to download per chunk (In MB). Defaults to 1 MB. | |
* @param boolean $returnbytes (Optional) Return number of bytes saved. Default: true | |
* | |
* @return integer Returns number of bytes delivered. | |
*/ | |
function downloadFile($srcName, $dstName, $chunkSize = 1, $returnbytes = true) { | |
$chunksize = $chunkSize*(1024*1024); // How many bytes per chunk | |
$data = ''; | |
$bytesCount = 0; | |
$handle = fopen($srcName, 'rb'); | |
$fp = fopen($dstName, 'w'); | |
if ($handle === false) { | |
return false; | |
} | |
while (!feof($handle)) { | |
$data = fread($handle, $chunksize); | |
fwrite($fp, $data, strlen($data)); | |
if ($returnbytes) { | |
$bytesCount += strlen($data); | |
} | |
} | |
$status = fclose($handle); | |
fclose($fp); | |
if ($returnbytes && $status) { | |
return $bytesCount; // Return number of bytes delivered like readfile() does. | |
} | |
return $status; | |
} | |
/** —————————————— | |
* Function Usage | |
* —————————————— | |
*/ | |
$bytes = downloadFile('http://wordpress.org/latest.zip', 'latest.zip'); |