Php 在通过HTTP加载数据之前确定文件大小
这可能吗?我目前正在使用cURL库用PHP编写代码,但这相当于整个HTTP 最明显的方法听起来像是向数据URL抛出HEAD请求并读取其内容长度头,但问题是,包括apache 2.0在内的一些服务器不针对HEAD请求发送内容长度,而且由于它不是强制性的,即使在GET请求时,也不能保证所有服务器都会回复此类信息 我让服务器下载用户输入指定的网页,并将其存储在服务器上,但我不想让它下载任何请求,结果发现文件太大,在下载所有内容后无法丢弃,从而阻塞恶意请求的带宽。 因此,我想在数据实际传输之前,可靠地了解内容的大小 恶意web服务器发送错误内容长度的案例和那些小的奇怪情况与我无关,如果它适用于所有其他一般情况的话 到目前为止,我心目中最糟糕的想法是,实际上只需使用GET请求下载内容,如果连接超过传输过程中指定的大小限制,则只需断开连接,但在HTTP这样的通用协议上,这听起来像是一个非常丑陋的解决方案Php 在通过HTTP加载数据之前确定文件大小,php,http,curl,Php,Http,Curl,这可能吗?我目前正在使用cURL库用PHP编写代码,但这相当于整个HTTP 最明显的方法听起来像是向数据URL抛出HEAD请求并读取其内容长度头,但问题是,包括apache 2.0在内的一些服务器不针对HEAD请求发送内容长度,而且由于它不是强制性的,即使在GET请求时,也不能保证所有服务器都会回复此类信息 我让服务器下载用户输入指定的网页,并将其存储在服务器上,但我不想让它下载任何请求,结果发现文件太大,在下载所有内容后无法丢弃,从而阻塞恶意请求的带宽。 因此,我想在数据实际传输之前,可靠地了
有人有更好的想法吗?没有,服务器不必告诉您他们将为您提供的资源的大小,因为他们自己可能不具备这些知识。因此,没有通用的方法,但是,是的,无论何时提供
内容长度标题,您都可以尝试查找它。我偶然发现了您的问题,正在寻找相同的答案。由于还没有真正的答案,我已经为自己设计了一个实现。当然,所有提到的注意事项仍然适用,是的,它确实使用了你的“丑陋”变体——但如果信息存在,这是实际获取数据的唯一方法
/**
* Returns the size reported by the server, for the given URL, in bytes.
*
* Note this information may not be accurate, or may even be plain wrong.
*
* Also note, the return value is explicitly NOT converted to an integer, as
* the remote file might be bigger than 2^31, which may mess up the number if
* you are on a 32bit machine.
*
* @throws InvalidArgumentException on unknown URL scheme
* @throws Exception when unable to connect
* @param string $url
* @returns int
*/
function getURLDownloadSize($url) {
$parts = parse_url($url);
if(isset($parts['port'])) {
$port = $parts['port'];
}
else {
$port = 80;
}
if($parts['scheme'] != 'http') {
throw new \InvalidArgumentException('Scheme not supported');
}
$sock = fsockopen($parts['host'], $port, $errno, $errstr, 3);
if(!$sock) {
throw new \Exception(
sprintf(
'Unable to connect to host: %s',
$errstr
)
);
}
stream_set_timeout($sock, 5);
fwrite($sock, sprintf("GET %s HTTP/1.1\r\n", $parts['path']));
fwrite($sock, sprintf("Host: %s\r\n", $parts['host']));
fwrite($sock, "Connection: close\r\n" );
fwrite($sock, "\r\n" );
$data = fread($sock, 1024*20);
fclose($sock);
$matchresult = array();
if (preg_match('/Content-Length:\s+(\d+)/', $data, $matchresult)) {
return $matchresult[1];
}
return 0;
}
这不是一个可靠的方法。似乎一旦连接超过给定的大小,就切断连接是唯一的方法。是的,不是,这就是为什么每当它被提供的时候。事实上,是的,即使提供了它,它也可能只对估计有帮助,因为没有什么可以阻止服务器发布10字节的内容,并向客户端提供/dev/uradom
的全部内容。