8月 5, 2022 -
php开发
php通过url下载大文件已关闭评论
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'); |