Gibt es eine Möglichkeit, die Größe einer Remote-Datei http://my_url/my_file.txt ohne Download der Datei zu bekommen?PHP: Remote-Dateigröße ohne Datei herunterladen
Antwort
Gefunden etwas über diesen here:
Hier ist der beste Weg, (die ich gefunden habe), um die Größe einer Remote- -Datei zu erhalten. Beachten Sie, dass HEAD-Anfragen nicht den eigentlichen Hauptteil der Anfrage erhalten, sie rufen nur die Header ab. Wenn Sie also eine HEAD-Anfrage an eine Ressource mit 100 MB stellen, wird dieselbe Zeit wie für eine HEAD-Anfrage an eine Ressource mit 1 KB benötigt.
<?php
/**
* Returns the size of a file without downloading it, or -1 if the file
* size could not be determined.
*
* @param $url - The location of the remote file to download. Cannot
* be null or empty.
*
* @return The size of the file referenced by $url, or -1 if the size
* could not be determined.
*/
function curl_get_file_size($url) {
// Assume failure.
$result = -1;
$curl = curl_init($url);
// Issue a HEAD request and follow any redirects.
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($curl, CURLOPT_USERAGENT, get_user_agent_string());
$data = curl_exec($curl);
curl_close($curl);
if($data) {
$content_length = "unknown";
$status = "unknown";
if(preg_match("/^HTTP\/1\.[01] (\d\d\d)/", $data, $matches)) {
$status = (int)$matches[1];
}
if(preg_match("/Content-Length: (\d+)/", $data, $matches)) {
$content_length = (int)$matches[1];
}
// http://en.wikipedia.org/wiki/List_of_HTTP_status_codes
if($status == 200 || ($status > 300 && $status <= 308)) {
$result = $content_length;
}
}
return $result;
}
?>
Verbrauch:
$file_size = curl_get_file_size("http://stackoverflow.com/questions/2602612/php-remote-file-size-without-downloading-file");
Sicher. Stellen Sie eine Header-Only-Anfrage, und suchen Sie nach dem Header Content-Length
.
Da diese Frage bereits markiert ist "php" und "Locke", ich nehme an, Sie wissen, wie Curl in PHP zu verwenden.
Wenn Sie curl_setopt(CURLOPT_NOBODY, TRUE)
setzen, dann werden Sie eine HEAD-Anfrage machen und können wahrscheinlich den Header "Content-Length" der Antwort überprüfen, der nur Header sein wird.
diesen Code Versuchen
function retrieve_remote_file_size($url){
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, TRUE);
curl_setopt($ch, CURLOPT_NOBODY, TRUE);
$data = curl_exec($ch);
$size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
curl_close($ch);
return $size;
}
die unten Funktion Versuchen Remote-Dateigröße
function remote_file_size($url){
$head = "";
$url_p = parse_url($url);
$host = $url_p["host"];
if(!preg_match("/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/",$host)){
$ip=gethostbyname($host);
if(!preg_match("/[0-9]*\.[0-9]*\.[0-9]*\.[0-9]*/",$ip)){
return -1;
}
}
if(isset($url_p["port"]))
$port = intval($url_p["port"]);
else
$port = 80;
if(!$port) $port=80;
$path = $url_p["path"];
$fp = fsockopen($host, $port, $errno, $errstr, 20);
if(!$fp) {
return false;
} else {
fputs($fp, "HEAD " . $url . " HTTP/1.1\r\n");
fputs($fp, "HOST: " . $host . "\r\n");
fputs($fp, "User-Agent: http://www.example.com/my_application\r\n");
fputs($fp, "Connection: close\r\n\r\n");
$headers = "";
while (!feof($fp)) {
$headers .= fgets ($fp, 128);
}
}
fclose ($fp);
$return = -2;
$arr_headers = explode("\n", $headers);
foreach($arr_headers as $header) {
$s1 = "HTTP/1.1";
$s2 = "Content-Length: ";
$s3 = "Location: ";
if(substr(strtolower ($header), 0, strlen($s1)) == strtolower($s1)) $status = substr($header, strlen($s1));
if(substr(strtolower ($header), 0, strlen($s2)) == strtolower($s2)) $size = substr($header, strlen($s2));
if(substr(strtolower ($header), 0, strlen($s3)) == strtolower($s3)) $newurl = substr($header, strlen($s3));
}
if(intval($size) > 0) {
$return=intval($size);
} else {
$return=$status;
}
if (intval($status)==302 && strlen($newurl) > 0) {
$return = remote_file_size($newurl);
}
return $return;
}
Dies ist der einzige, der für mich auf Ubuntu Linux Apache Server funktioniert. Ich musste zu Beginn der Funktion $ size und $ status initiieren, sonst funktionierte es so wie es ist. –
Die meisten Antworten hier verwendet entweder ROTATION oder gründend auf das Lesen Header zu erhalten. Aber in bestimmten Situationen können Sie eine einfachere Lösung verwenden. Hinweis auf filesize()
's docs on PHP.net beachten. Dort finden Sie einen Tipp: "Ab PHP 5.0.0 kann diese Funktion auch mit einigen URL-Wrappern verwendet werden. Unter können Sie ermitteln, welche Wrapper die stat() - Funktionsfamilie unterstützen".
Also, wenn Ihr Server und PHP-Parser richtig konfiguriert ist, können Sie einfach filesize()
Funktion verwenden, fütterte es mit voller URL, zeigt auf eine Remote-Datei, welche Größe Sie erhalten möchten, und lassen PHP die ganze Magie tun.
Die einfachste und effizienteste UMSETZUNG:
function remote_filesize($url) {
static $regex = '/^Content-Length: *+\K\d++$/im';
if (!$fp = @fopen($url, 'rb')) {
return false;
}
if (
isset($http_response_header) &&
preg_match($regex, implode("\n", $http_response_header), $matches)
) {
return (int)$matches[0];
}
return strlen(stream_get_contents($fp));
}
Arbeitete wie Magie. Vielen Dank. – rottenoats
Ich bin nicht sicher, aber Sie verwenden konnte die get_headers Funktion für das?
$url = 'http://example.com/dir/file.txt';
$headers = get_headers($url, true);
if (isset($headers['Content-Length'])) {
$size = 'file size:' . $headers['Content-Length'];
}
else {
$size = 'file size: unknown';
}
echo $size;
Mit diesem Beispiel ist es möglich, dass der Zielserver unter $ url get_headers ausnutzt, um die Verbindung offen zu halten, bis der PHP-Prozess abläuft (indem die Header sehr langsam zurückgegeben werden, während die Verbindung nicht langsam genug wird). Da die gesamten PHP-Prozesse möglicherweise durch FPM begrenzt sind, kann dies eine Art langsamen Loris-Angriff ermöglichen, wenn mehrere Benutzer gleichzeitig auf Ihr Skript get_headers zugreifen. –
Wie bereits erwähnt ein paar Mal, den Weg zu gehen ist die Informationen aus der Antwort-Header des Content-Length
Feld abzurufen.
Sie sollten jedoch beachten, dass
- der Server, den Sie nicht unbedingt implementiert die HEAD-Methode Sondieren (!)
- gibt es absolut keine Notwendigkeit, manuell eine HEAD-Anfrage zu fertigen (die wiederum vielleicht nicht einmal unterstützt werden)
fopen
oder gleich oder sogar mit der curl-Bibliothek aufrufen, wenn PHPget_headers()
hat (zur Erinnerung: K.I.S.S.)
Verwendung von get_headers()
folgt die K.I.S.S. principleund funktioniert, auch wenn der Server, den Sie sondieren, die HEAD-Anfrage nicht unterstützt. So
, hier ist meine Version (Gimmick: gibt den Menschen lesbaren formatiert Größe ;-)):
Gist: https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d (curl und get_headers Version)
get_headers() - Version:
<?php
/**
* Get the file size of any remote resource (using get_headers()),
* either in bytes or - default - as human-readable formatted string.
*
* @author Stephan Schmitz <[email protected]>
* @license MIT <http://eyecatchup.mit-license.org/>
* @url <https://gist.github.com/eyecatchup/f26300ffd7e50a92bc4d>
*
* @param string $url Takes the remote object's URL.
* @param boolean $formatSize Whether to return size in bytes or formatted.
* @param boolean $useHead Whether to use HEAD requests. If false, uses GET.
* @return string Returns human-readable formatted size
* or size in bytes (default: formatted).
*/
function getRemoteFilesize($url, $formatSize = true, $useHead = true)
{
if (false !== $useHead) {
stream_context_set_default(array('http' => array('method' => 'HEAD')));
}
$head = array_change_key_case(get_headers($url, 1));
// content-length of download (in bytes), read from Content-Length: field
$clen = isset($head['content-length']) ? $head['content-length'] : 0;
// cannot retrieve file size, return "-1"
if (!$clen) {
return -1;
}
if (!$formatSize) {
return $clen; // return size in bytes
}
$size = $clen;
switch ($clen) {
case $clen < 1024:
$size = $clen .' B'; break;
case $clen < 1048576:
$size = round($clen/1024, 2) .' KiB'; break;
case $clen < 1073741824:
$size = round($clen/1048576, 2) . ' MiB'; break;
case $clen < 1099511627776:
$size = round($clen/1073741824, 2) . ' GiB'; break;
}
return $size; // return formatted size
}
Verbrauch:
$url = 'http://download.tuxfamily.org/notepadplus/6.6.9/npp.6.6.9.Installer.exe';
echo getRemoteFilesize($url); // echoes "7.51 MiB"
Zusätzliche Anmerkung: Der Content-Length-Header ist optional. Somit ist es als allgemeine Lösung nicht kugelsicher!
Dies sollte die akzeptierte Antwort sein. True, 'Content-Length' ist optional, aber es ist der einzige Weg, um die Dateigröße ohne Download zu erhalten - und' get_headers' ist der beste Weg, 'content-length' zu erhalten. –
Hier ist ein weiterer Ansatz, die mit Servern arbeiten, die HEAD
Anfragen nicht unterstützen.
Es verwendet cURL, um eine Anforderung für den Inhalt mit einem HTTP-Bereich Header nach dem ersten Byte der Datei zu fragen.
Wenn der Server Bereichsanforderungen unterstützt (die meisten Medienserver werden dies tun), erhält er die Antwort mit der Größe der Ressource.
Wenn der Server nicht mit einem Bytebereich antwortet, sucht er nach einem Inhaltslängenheader, um die Länge zu bestimmen.
Wenn die Größe in einem Bereich oder Header für Inhaltslänge gefunden wird, wird die Übertragung abgebrochen. Wenn die Größe nicht gefunden wird und die Funktion beginnt, den Antworttext zu lesen, wird die Übertragung abgebrochen.
Dies könnte ein zusätzlicher Ansatz sein, wenn eine HEAD
Anfrage zu einer 405
Methode führt, die nicht unterstützt wird.
/**
* Try to determine the size of a remote file by making an HTTP request for
* a byte range, or look for the content-length header in the response.
* The function aborts the transfer as soon as the size is found, or if no
* length headers are returned, it aborts the transfer.
*
* @return int|null null if size could not be determined, or length of content
*/
function getRemoteFileSize($url)
{
$ch = curl_init($url);
$headers = array(
'Range: bytes=0-1',
'Connection: close',
);
$in_headers = true;
$size = null;
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2450.0 Iron/46.0.2450.0');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 0); // set to 1 to debug
curl_setopt($ch, CURLOPT_STDERR, fopen('php://output', 'r'));
curl_setopt($ch, CURLOPT_HEADERFUNCTION, function($curl, $line) use (&$in_headers, &$size) {
$length = strlen($line);
if (trim($line) == '') {
$in_headers = false;
}
list($header, $content) = explode(':', $line, 2);
$header = strtolower(trim($header));
if ($header == 'content-range') {
// found a content-range header
list($rng, $s) = explode('/', $content, 2);
$size = (int)$s;
return 0; // aborts transfer
} else if ($header == 'content-length' && 206 != curl_getinfo($curl, CURLINFO_HTTP_CODE)) {
// found content-length header and this is not a 206 Partial Content response (range response)
$size = (int)$content;
return 0;
} else {
// continue
return $length;
}
});
curl_setopt($ch, CURLOPT_WRITEFUNCTION, function($curl, $data) use ($in_headers) {
if (!$in_headers) {
// shouldn't be here unless we couldn't determine file size
// abort transfer
return 0;
}
// write function is also called when reading headers
return strlen($data);
});
$result = curl_exec($ch);
$info = curl_getinfo($ch);
return $size;
}
Verbrauch:
$size = getRemoteFileSize('http://example.com/video.mp4');
if ($size === null) {
echo "Could not determine file size from headers.";
} else {
echo "File size is {$size} bytes.";
}
Php Funktion get_headers()
Werke für mich zu überprüfen, den content-length als
$headers = get_headers('http://example.com/image.jpg', TRUE);
$filesize = $headers['content-length'];
Weiteres Detail: PHP Function get_headers()
Für mich (mit nginx) war der Header Content-Length – Pangamma
eine Zeile am besten Lösung:
echo array_change_key_case(get_headers("http://.../file.txt",1))['content-length'];
PHP ist zu delicius
function urlsize($url):int{
return array_change_key_case(get_headers($url,1))['content-length'];
}
echo urlsize("http://.../file.txt");
ich las, dass früher, nicht sicher war, ob Content-Length die Länge oder die Dateigröße gemeint – dassouki
gut, wenn die Anforderung eine Datei zurückgibt, die Anforderungsgröße * ist * die Dateigröße – Gareth
Aber bedenken Sie, dass es Antworten ohne Content-Länge geben kann. – VolkerK