/** * Download a file to the filesystem. * * @param string $url * @param string $filename * @param array $options * @param bool $async * * @throws Exception * * @return Curl */ public static function download($url, $filename, $options = [], $async = false) { $fp = fopen($filename, 'w'); if ($fp === false) { throw new Exception('Unable to write to "' . $filename . '"'); } flock($fp, LOCK_EX); $defaults = self::defaults(array(CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => false, CURLOPT_FILE => $fp)); $response = new self($options + $defaults); $response->on('load', function () use($fp) { fflush($fp); flock($fp, LOCK_UN); }); $deleteFile = function () use($filename, &$fp) { flock($fp, LOCK_UN); fclose($fp); unlink($filename); $fp = fopen('php://memory', 'w'); }; $response->on('abort', $deleteFile); // Override default error handle $response->onError = function ($message, $options) use($deleteFile) { $deleteFile(); throw new InfoException($message, $options); }; $response->on('closed', function ($response) use(&$fp) { fclose($fp); }); if ($async == false) { $response->waitForCompletion(); } return $response; }