Я использую readfile, чтобы позволить клиенту загрузить файл через мой сервер.Для этого я вывожу данные, которые я получаю из readfile ('external-url'), прямо на клиент.
Теперь я хочу определить трафик, который вызывается readfile ().
Iможет определить его по возвращаемому значению readfile, но только если клиент заканчивает загрузку.В противном случае скрипт перестает работать, и возвращаемое значение readfile () равно 0.
Сначала я попробовал этот код:
//outputs download headers
//creating $stream_context with request headers for the external download server
$traffic = readfile($url, false, $stream_context);
//save traffic...
Сохранение трафика никогда не вызывалось, когда клиент прекращал загрузку.
Затем я зарегистрировал функцию shutdown с помощью register_shutdown_function (), которая включала $ traffic в качестве глобальной переменной для сохранения трафика.Теперь файл трафика был создан, но использовался трафик 0.
У меня нет доступа к журналам сервера или что-то еще.Я могу использовать только php и htaccess.
Один из способов, который я сейчас использую, заключается в том, что я запускаю запрос к файлу, анализирую размер файла и добавляю полный размер файла в трафик клиента.Затем я начинаю загрузку с readfile ().Если клиент прекращает загрузку, он обрабатывается так, как если бы он загружал весь файл.
Третий метод может быть curl и его CURLOPT_WRITEFUNCTION-settings.Но это слишком много для сервера и не имеет никакого отношения к тому, что я хочу сделать: сохранить реальный трафик.
Существует также другая проблема с сохранением трафика клиента перед загрузкой файла: я хочуподдержка возобновления и частичной загрузки (несколько подключений к одному файлу для более быстрой загрузки).Это все еще работает, но проблема в подсчете трафика!Для кусков я могу разобрать заголовок HTTP-RANGE, чтобы определить запрошенные части файла и сохранить его как трафик, но как насчет возобновления?
Так есть ли какое-нибудь возможное решение в мире?
Я до сих пор не использую базу данных, я использую только файл с htaccess -logininformation для идентификации клиентов и сохранения использованного трафика для каждого клиента в отдельном файле на моем веб-пространстве.
Вот также мой код:
//$download = array(url, filesize, filename) got it whith a separate curl request to the external file
$downloadHeader = CreateDownloadHeaders($download, $_hoster->AcceptRanges());
$requestOptions = array(
'http'=>array(
'method' => 'GET',
'header' => CreateRequestHeaders($download['filesize'], $_hoster->AcceptRanges())
)
);
$requestOptions['http']['header'] = array_merge($requestOptions['http']['header'], $_hoster->GetAdditionalHeaders());
//Output download headers for our client
foreach($downloadHeader as $header) {
header($header);
}
register_shutdown_function('SaveTraffic', $username, $givenUrl, $download['filename'], $download['filesize']);
//SaveTraffic($username, $givenUrl, $download['filename'], $download['filesize']);
$context = stream_context_create($requestOptions);
$traffic = readfile($download['url'], false, $context);
А теперь функции:
function CreateDownloadHeaders($download, $acceptRanges) {
//IE workaround for downloads
$type = (isset($_SERVER['HTTP_USER_AGENT']) && strpos($_SERVER['HTTP_USER_AGENT'],'MSIE')) ? 'force-download' : 'octet-stream';
$headers = array(
'Content-Type: application/' . $type,
'Content-Disposition: attachment; filename="'.$download['filename'].'"',
'Content-Length: '.$download['filesize'],
'Content-Transfer-Encoding: Binary',
'Expires: 0',
'Cache-Control: must-revalidate, post-check=0, pre-check=0',
'Pragma: public',
'Connection: close'
);
$headers = AddDownloadRangeHeaders($headers, $acceptRanges, $download['filesize']);
return $headers;
}
function CreateRequestHeaders($filesize, $acceptRanges) {
$headers = array();
$headers = AddRequestRangeHeaders($headers, $acceptRanges, $filesize);
$headers[] = 'User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.1; de; rv:1.9.2.13) Gecko/20101203 Firefox/3.6.13';
$headers[] = 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8';
$headers[] = 'Accept-Language: de, en-gb;q=0.9, en;q=0.8';
$headers[] = 'Accept-Encoding: gzip, deflate';
$headers[] = 'Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7';
$headers[] = 'Cache-Control: no-cache';
$headers[] = 'Pragma: no-cache';
$headers[] = 'Connection: close';
return $headers;
}
function AddDownloadRangeHeaders($headers, $acceptRanges, $filesize) {
if($acceptRanges !== true) {
$headers[] = 'Accept-Ranges: none';
}
elseif(isset($_SERVER['HTTP_RANGE'])) {
preg_match('/bytes([[:space:]])?=([[:space:]])?(\d+)?-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
$start = intval($matches[3]);
$stop = intval($matches[4]);
if($stop == 0) {
$stop = $filesize;
}
$headers[] = 'HTTP/1.1 206 Partial Content';
$headers[] = 'Accept-Ranges: bytes';
$headers[] = 'Content-Range: bytes ' . $start . '-' . $stop . '/' . $filesize;
$newSize = $stop - $start + 1;
$key = array_search('Content-Length: '.$filesize, $headers);
$headers[$key] = 'Content-Length: '.$newSize;
}
return $headers;
}
function AddRequestRangeHeaders($headers, $acceptRanges, $filesize) {
if($acceptRanges === true && isset($_SERVER['HTTP_RANGE'])) {
preg_match('/bytes([[:space:]])?=([[:space:]])?(\d+)?-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
$start = intval($matches[3]);
$stop = intval($matches[4]);
if($stop == 0) {
$stop = $filesize;
}
$headers[] = 'Range: bytes='.$start.'-'.$stop;
}
return $headers;
}