PHP의 libcurl 기반 컬 함수를 사용하면 대상 URL에 대한 http 요청을 시작하고 반환된 응답 콘텐츠를 얻을 수 있습니다. 일반적인 요청 방법은 다음 코드와 유사합니다.
public function callFunction($url, $postData, $method, header='') { $maxRetryTimes = 3; $curl = curl_init(); /******初始化请求参数start******/ if(strtoupper($method) !== 'GET' && $postData){ curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($postData)); }elseif (strtoupper($method) === 'GET' && $postData){ $url .= '?'. http_build_query($postData); } /******初始化请求参数end******/ curl_setopt_array($curl, array( CURLOPT_URL => $url, CURLOPT_TIMEOUT => 10, CURLOPT_NOBODY => 0, CURLOPT_RETURNTRANSFER => 1 )); if(method == 'POST'){ curl_setopt($curl, CURLOPT_POST, true); } if(false == empty()){ curl_setopt($curl, CURLOPT_HTTPHEADER, $header); } $response = false; while(($response === false) && (--$maxRetryTimes > 0)){ $response = trim(curl_exec($curl)); } return $response; }
위 코드의 $response는 $에서 범위로 지정되지 않은 경우 컬에 의해 시작된 이 http 요청의 $url에서 얻은 데이터입니다. 헤더 다운로드할 리소스의 크기에 관계없이 URI의 전체 콘텐츠를 요청하고 반환해야 합니다. 일반적으로 컬은 일부 인터페이스를 요청하거나 데이터를 얻기 위해 원격으로 함수를 호출하는 데만 사용되므로 이 시나리오에서는 CURLOPT_TIMEOUT 매개변수가 매우 중요합니다.
컬의 사용 시나리오는 데이터 인터페이스에 액세스하는 것뿐만 아니라 URL 리소스가 올바른 http 서비스를 제공할 수 있는지 여부를 감지하는 것입니다. 사용자가 입력한 URL이 pdf, ppt 등의 리소스 파일인 경우, 네트워크 상태가 좋지 않아 컬을 사용하여 더 큰 리소스를 요청하게 되면 필연적으로 타임아웃이 발생하거나 인터넷 리소스가 더 많이 소모됩니다. . 이전 전략은 완전히 다운로드하는 것이었습니다(curl은 이를 다운로드하여 메모리에 저장합니다). 요청이 완료된 후 콘텐츠 크기를 확인하여 대상 값을 초과하면 모니터링 작업이 일시 중지됩니다. 사고 이후의 이러한 제한은 실제로 근본 원인이 아닌 증상을 해결했습니다. 결국 고객은 작업을 중지할 수 없으며 지정된 크기의 파일만 다운로드되고 고객에게 md5 값이 반환되었습니다. 정확성을 확인하십시오.
몇번의 시도 끝에 이 문제는 해결되었습니다. 녹음 과정은 다음과 같습니다.
1. CURLOPT_MAXFILESIZE를 사용해 보세요.
PHP 및 libcurl 버전에는 버전 요구 사항이 있는데, 이는 완전히 전처리되어 대상이 설정보다 큰 것으로 확인되면 대상을 다운로드하지 않고 크기 제한을 초과하는 오류가 직접 반환되므로 충족되지 않습니다. 요구 사항.
2. 컬 다운로드 프로세스의 콜백 기능을 사용합니다.
http://php.net/manual/en/function.curl-setopt-array.php를 참조하고 마지막으로 CURLOPT_WRITEFUNCTION 매개변수를 사용하여 on_curl_write를 설정합니다. 이 함수는 1초에 한 번 호출됩니다.
$ch = curl_init(); $options = array(CURLOPT_URL => 'http://www.php.net/', CURLOPT_HEADER => false, CURLOPT_HEADERFUNCTION => 'on_curl_header', CURLOPT_WRITEFUNCTION => 'on_curl_write' );
내 구현의 마지막 조각:
function on_curl_write($ch, $data) { $pid = getmypid(); $downloadSizeRecorder = DownloadSizeRecorder::getInstance($pid); $bytes = strlen($data); $downloadSizeRecorder->downloadData .= $data; $downloadSizeRecorder->downloadedFileSize += $bytes; // error_log(' on_curl_write '.$downloadSizeRecorder->downloadedFileSize." > {$downloadSizeRecorder->maxSize} \n", 3, '/tmp/hyb.log'); //确保已经下载的内容略大于最大限制 if (($downloadSizeRecorder->downloadedFileSize - $bytes) > $downloadSizeRecorder->maxSize) { return false; } return $bytes; //这个不正确的返回,将会报错,中断下载 "errno":23,"errmsg":"Failed writing body (0 != 16384)"}
DownloadSizeRecorder는 컬이 다운로드될 때 크기를 기록하고 다운로드한 콘텐츠의 md5 등을 반환하는 싱글톤 모드 클래스입니다.
class DownloadSizeRecorder { const ERROR_FAILED_WRITING = 23; //Failed writing body public $downloadedFileSize; public $maxSize; public $pid; public $hasOverMaxSize; public $fileFullName; public $downloadData; private static $selfInstanceList = array(); public static function getInstance($pid) { if(!isset(self::$selfInstanceList[$pid])){ self::$selfInstanceList[$pid] = new self($pid); } return self::$selfInstanceList[$pid]; } private function __construct($pid) { $this->pid = $pid; $this->downloadedFileSize = 0; $this->fileFullName = ''; $this->hasOverMaxSize = false; $this->downloadData = ''; } /** * 保存文件 */ public function saveMaxSizeData2File(){ if(empty($resp_data)){ $resp_data = $this->downloadData; } $fileFullName = '/tmp/http_'.$this->pid.'_'.time()."_{$this->maxSize}.download"; if($resp_data && strlen($resp_data)>0) { list($headerOnly, $bodyOnly) = explode("\r\n\r\n", $resp_data, 2); $saveDataLenth = ($this->downloadedFileSize < $this->maxSize) ? $this->downloadedFileSize : $this->maxSize; $needSaveData = substr($bodyOnly, 0, $saveDataLenth); if(empty($needSaveData)){ return; } file_put_contents($fileFullName, $needSaveData); if(file_exists($fileFullName)){ $this->fileFullName = $fileFullName; } } } /** * 返回文件的md5 * @return string */ public function returnFileMd5(){ $md5 = ''; if(file_exists($this->fileFullName)){ $md5 = md5_file($this->fileFullName); } return $md5; } /** * 返回已下载的size * @return int */ public function returnSize(){ return ($this->downloadedFileSize < $this->maxSize) ? $this->downloadedFileSize : $this->maxSize; } /** * 删除下载的文件 */ public function deleteFile(){ if(file_exists($this->fileFullName)){ unlink($this->fileFullName); } } }
컬 요청의 코드 예시에서는 다운로드 크기가 제한되어 있습니다.
…… curl_setopt($ch, CURLOPT_WRITEFUNCTION, 'on_curl_write');//设置回调函数 …… $pid = getmypid(); $downloadSizeRecorder = DownloadSizeRecorder::getInstance($pid); $downloadSizeRecorder->maxSize = $size_limit; …… //发起curl请求 $response = curl_exec($ch); …… //保存文件,返回md5 $downloadSizeRecorder->saveMaxSizeData2File(); //保存 $downloadFileMd5 = $downloadSizeRecorder->returnFileMd5(); $downloadedfile_size = $downloadSizeRecorder->returnSize(); $downloadSizeRecorder->deleteFile();
이때 구덩이를 밟았습니다. on_curl_write를 추가한 후 $response는 true를 반환하므로 나중에 반환된 콘텐츠를 가져올 때 예외가 발생합니다. 다행스럽게도 다운로드 크기가 실시간으로 제한되어 있으며 downloadData는 다운로드한 콘텐츠를 기록하는 데 사용되며 직접 사용할 수 있습니다.
rreee
위 내용은 PHP가 컬을 사용하여 지정된 크기의 파일을 다운로드하는 방법의 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!