Сегодня потребовалось реализовать сервис, который будет проверять файлы на доступность, т.е. просто получать код http ответ-а от сервера, есть ли такой файл или нет. Обрабатывать надо много файлов, поэтому нужно было найти самое быстрое решение..
Из известных мне способов, есть три с помощью которых можно это сделать на php: curl, get_headers, и fsockopen. Я решил написать мини скрипт и протестировать все три способа. Тем более кодить ничего не пришлось, весь нужный функционал уже описан в комментах на php.net. Итак, у меня получилась такая програмка:
<?php set_time_limit(300); ob_implicit_flush(true); function get_headers_curl($url) { $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_HEADER, true); curl_setopt($ch, CURLOPT_NOBODY, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 15); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); $r = curl_exec($ch); $r = explode("\n", $r); return $r; } function get_http_response_code($theURL) { $ret = @get_headers($theURL); return $ret; } function get_headers_socket($Url, $Format= 0, $Depth= 0) { if ($Depth > 5) return; $Parts = parse_url($Url); if (!array_key_exists('path', $Parts)) $Parts['path'] = '/'; if (!array_key_exists('port', $Parts)) $Parts['port'] = 80; if (!array_key_exists('scheme', $Parts)) $Parts['scheme'] = 'http'; $Return = array(); $fp = @fsockopen($Parts['host'], $Parts['port'], $errno, $errstr, 30); if ($fp) { $Out = 'GET '.$Parts['path'].(isset($Parts['query']) ? '?'.@$Parts['query'] : '')." HTTP/1.1\r\n". 'Host: '.$Parts['host'].($Parts['port'] != 80 ? ':'.$Parts['port'] : '')."\r\n". 'Connection: Close'."\r\n"; fwrite($fp, $Out."\r\n"); $Redirect = false; $RedirectUrl = ''; while (!feof($fp) && $InLine = fgets($fp, 1280)) { if ($InLine == "\r\n") break; $InLine = rtrim($InLine); list($Key, $Value) = explode(': ', $InLine, 2); if ($Key == $InLine) { if ($Format == 1) $Return[$Depth] = $InLine; else $Return[] = $InLine; if (strpos($InLine, 'Moved') > 0) $Redirect = true; } else { if ($Key == 'Location') $RedirectUrl = $Value; if ($Format == 1) $Return[$Key] = $Value; else $Return[] = $Key.': '.$Value; } } fclose($fp); if ($Redirect && !empty($RedirectUrl)) { $NewParts = parse_url($RedirectUrl); if (!array_key_exists('host', $NewParts)) $RedirectUrl = $Parts['host'].$RedirectUrl; if (!array_key_exists('scheme', $NewParts)) $RedirectUrl = $Parts['scheme'].'://'.$RedirectUrl; $RedirectHeaders = get_headers_socket($RedirectUrl, $Format, $Depth+1); if ($RedirectHeaders) $Return = array_merge_recursive($Return, $RedirectHeaders); } return $Return; } return false; } $urls = array( 'http://www.kleentek123456789.com/pdfs/OilManagement.pdf', 'http://www.kleentek.com/pdfs/OilManagement.pdf', 'http://www.interoncorp.com/pdfs/996470.pdf', 'http://www.ramflat.com/pdf/aerosolv.pdf', 'http://www.fpl.com/rates/pdf/lowbillR.pdf', 'http://www.ced.umn.edu/forms/directory1.pdf', 'http://www.strazishar.com/bulletin/page09.pdf', 'http://bobdaubney.com/image2/THESTATEOFBOWLING.pdf', 'http://www.4strokes.com/tech/exh_tune.pdf', 'http://www.hatfieldmetal.com/hmfbrochure.pdf', 'https://www.loveandlogic.com/Media/classroom.pdf', 'http://www.hchsa.net/Newsletters/News08Fall.pdf', 'http://www.fedstarcu.com/pdf/newsletter.pdf', 'https://www.jscfcu.org/docs/membership-star.pdf', 'http://www.ok.gov/~osbd/Closed/closcred.pdf', 'http://www.stepforwardmichigan.org/rfv-72.aspx', 'http://www.unitedccu.com/pdf/10_Annual_Report.pdf', 'http://www.lasc.org/opinions/92ka2639.opn.pdf', 'http://lake-viewcemetery.com/burials/wa_z.pdf', 'http://www.forsythnchistory.com/files/whitaker.pdf', 'http://www.ajlambert.com/cemetery/cmty_clc2.pdf', 'http://www.bvarc.org/Tech/amplifiers.pdf', 'http://www.minikits.com.au/doc/MMICSc.pdf', ); echo '<body style="font-family:Tahoma; font-size:11px;">'; $work_time_res = array(); echo '<h3>CURL</h3>'; echo '<div style="height:200px;overflow:auto; border:1px solid silver;padding:10px;margin-bottom:5px;">'; $start_time = time(); foreach ($urls as $url) { $answer = get_headers_curl($url); if ($answer) $answer = implode("\n",$answer); echo date('H:i:s').' - '.$url.'<br>ANSWER: '.$answer.'<br><br>'; } $work_time_res['CURL'] = time()-$start_time; echo '</div>'; echo 'Work time: '.$work_time_res['CURL'].'sec<br>'; echo '<hr>'; echo '<h3>GET_HEADERS</h3>'; echo '<div style="height:200px;overflow:auto; border:1px solid silver;padding:10px;margin-bottom:5px;">'; $start_time = time(); foreach ($urls as $url) { $answer = @get_http_response_code($url); if ($answer) $answer = implode("\n",$answer); echo date('H:i:s').' - '.$url.'<br>ANSWER: '.$answer.'<br><br>'; } $work_time_res['GET_HEADERS'] = time()-$start_time; echo '</div>'; echo 'Work time: '.$work_time_res['GET_HEADERS'].'sec<br>'; echo '<hr>'; echo '<h3>GET_HEADERS_SOCKET</h3>'; echo '<div style="height:200px;overflow:auto; border:1px solid silver;padding:10px;margin-bottom:5px;">'; $start_time = time(); foreach ($urls as $url) { $answer = get_headers_socket($url); if ($answer) $answer = implode("\n",$answer); echo date('H:i:s').' - '.$url.'<br>ANSWER: '.$answer.'<br><br>'; } $work_time_res['GET_HEADERS_SOCKET'] = time()-$start_time; echo '</div>'; echo 'Work time: '.$work_time_res['GET_HEADERS_SOCKET'].'sec<br>'; echo '<hr>'; echo '<h3>WORK TIME</h3>'; foreach($work_time_res as $func=>$time) echo $func.' = '.count($urls).' urls in '.$time.' sec<br>'; echo '</body>';
В качестве документов, я взял первый нашедшийся список pdf-ов, однако можно взять и любые другие файлы, это не важно.
Результаты получились вот такие:
CURL = 23 urls in 9 sec
GET_HEADERS = 23 urls in 11 sec
GET_HEADERS_SOCKET = 23 urls in 10 sec
Вот так выглядит лог работы:
После нескольких запусков, особо ничего не меняется, CURL чаще все немного впереди. Я примерно так и думал, но были сомнения, теперь буду использовать его с уверенностью, что это лучшее решение для моей задачи.