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');

评论被关闭。