国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

php使用curl下載指定大小的文件實例代碼

2024-05-05 00:00:20
字體:
來源:轉載
供稿:網友

php中使用基于libcurl的curl函數,可以對目標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是curl發起的這次http請求從$url獲取到的數據,如果沒有在$header中通過range來指定要下載的大小,無論這個資源多大,那么都要請求完整的并返回的是這個URI的完整內容。通常只用curl來請求求一些接口或者遠程調用一個函數獲取數據,,所以這個場景下CURLOPT_TIMEOUT這個參數很重要。

對于curl的使用場景不止訪問數據接口,還要對任意的url資源進行檢測是否能提供正確的http服務。當用戶填入的url是一個資源文件時,例如一個pdf或者ppt之類的,這時候如果網絡狀況較差的情況下用curl請求較大的資源,將不可避免的出現超時或者耗費更多的網絡資源。之前的策略是完全下載(curl會下載存儲在內存中),請求完后檢查內容大小,當超過目標值就把這個監控的任務暫停。這樣事發后限制其實治標不治本,終于客戶提出了新的需求,不能停止任務只下載指定大小的文件并返回md5值由客戶去校驗正確性。

經過了一些嘗試,解決了這個問題,記錄過程如下文。

1、嘗試使用 CURLOPT_MAXFILESIZE。

對php和libcurl的版本有版本要求,完全的事前處理,當發現目標大于設置時,直接返回了超過大小限制的錯誤而不去下載目標了,不符合要求。

2、使用curl下載過程的回調函數。

參考 http://php.net/manual/en/function.curl-setopt-array.php ,最終使用了CURLOPT_WRITEFUNCTION參數設置了on_curl_write,該函數將會1s中被回調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是一個單例模式的類,curl下載時記錄大小,實現返回下載內容的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請求的代碼實例中,實現限制下載大小

……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來記錄了已經下載的內容,直接可以使用。

if($response === true){  $response = $downloadSizeRecorder->downloadData;}

總結

以上所述是小編給大家介紹的php使用curl下載指定大小的文件,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VeVb武林網網站的支持!


注:相關教程知識閱讀請移步到PHP教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

主站蜘蛛池模板: 兴业县| 钟山县| 遵义市| 辉南县| 石河子市| 阿荣旗| 高安市| 宣恩县| 大理市| 河北省| 沙雅县| 玉溪市| 保亭| 大洼县| 台山市| 丽江市| 临沂市| 安仁县| 隆安县| 额尔古纳市| 龙海市| 汪清县| 曲阜市| 霍林郭勒市| 德阳市| 中牟县| 黎城县| 安福县| 长岭县| 诸暨市| 福泉市| 天峨县| 共和县| 博客| 双柏县| 平阴县| 沙湾县| 肇州县| 通渭县| 蓬莱市| 大埔县|