我需要直接向客戶端下載遠程文件。一些谷歌搜索後,我發現這個腳本在PHP手冊,但其恢復能力不起作用。該腳本使用Http_Range
生成可恢復的下載鏈接。有沒有其他方法可以做到這一點?當然,這將使用cUrl
,但我需要將遠程文件直接下載到客戶端。我該如何解決這個問題?將遠程文件直接下載到客戶端?
<?php
$url="http://dl.remote-domain.com/files/file.mp4";
dl_file_resumable($url);
function dl_file_resumable($file, $is_resume=TRUE)
{
//Gather relevent info about file
$size = remotefilesize($file);
$fileinfo = pathinfo($file);
//workaround for IE filename bug with multiple periods/multiple dots in filename
//that adds square brackets to filename - eg. setup.abc.exe becomes setup[1].abc.exe
$filename = (strstr($_SERVER['HTTP_USER_AGENT'], 'MSIE')) ?
preg_replace('/\./', '%2e', $fileinfo['basename'], substr_count($fileinfo
['basename'], '.') - 1) :
$fileinfo['basename'];
$file_extension = strtolower($path_info['extension']);
//This will set the Content-Type to the appropriate setting for the file
switch($file_extension)
{
case 'exe': $ctype='application/octet-stream'; break;
case 'zip': $ctype='application/zip'; break;
case 'mp3': $ctype='audio/mpeg'; break;
case 'mpg': $ctype='video/mpeg'; break;
case 'avi': $ctype='video/x-msvideo'; break;
default: $ctype='application/force-download';
}
//check if http_range is sent by browser (or download manager)
if($is_resume && isset($_SERVER['HTTP_RANGE']))
{
list($size_unit, $range_orig) = explode('=', $_SERVER['HTTP_RANGE'], 2);
if ($size_unit == 'bytes')
{
//multiple ranges could be specified at the same time, but for simplicity only
serve the first range
//http://tools.ietf.org/id/draft-ietf-http-range-retrieval-00.txt
list($range, $extra_ranges) = explode(',', $range_orig, 2);
}
else
{
$range = '';
}
}
else
{
$range = '';
}
//figure out download piece from range (if set)
list($seek_start, $seek_end) = explode('-', $range, 2);
//set start and end based on range (if set), else set defaults
//also check for invalid ranges.
$seek_end = (empty($seek_end)) ? ($size - 1) : min(abs(intval($seek_end)),($size - 1));
$seek_start = (empty($seek_start) || $seek_end < abs(intval($seek_start))) ? 0 : max(abs
(intval($seek_start)),0);
//add headers if resumable
if ($is_resume)
{
//Only send partial content header if downloading a piece of the file (IE workaround)
if ($seek_start > 0 || $seek_end < ($size - 1))
{
header('HTTP/1.1 206 Partial Content');
}
header('Accept-Ranges: bytes');
header('Content-Range: bytes '.$seek_start.'-'.$seek_end.'/'.$size);
}
//headers for IE Bugs (is this necessary?)
//header("Cache-Control: cache, must-revalidate");
//header("Pragma: public");
header('Content-Type: ' . $ctype);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Length: '.($seek_end - $seek_start + 1));
//open the file
$fp = fopen($file, 'rb');
//seek to start of missing part
fseek($fp, $seek_start);
//start buffered download
while(!feof($fp))
{
//reset time limit for big files
set_time_limit(0);
print(fread($fp, 1024*8));
flush();
ob_flush();
}
fclose($fp);
exit;
}
function remotefilesize($url, $user = "", $pw = "")
{
ob_start();
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_NOBODY, 1);
if(!empty($user) && !empty($pw))
{
$headers = array('Authorization: Basic ' . base64_encode("$user:$pw"));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
}
$ok = curl_exec($ch);
curl_close($ch);
$head = ob_get_contents();
ob_end_clean();
$regex = '/Content-Length:\s([0-9].+?)\s/';
$count = preg_match($regex, $head, $matches);
return isset($matches[1]) ? $matches[1] : "unknown";
}
?>
當前腳本的確切問題是什麼? – Baba