PHP 5.3.4, cURL 7.24.0, Windows 7 SP1 64b
Ich rufe das folgende Skript an der Windows-Eingabeaufforderung (CMD) auf; es soll eine große ZIP-Datei (~128 MB) herunterladen werden, falls sie nicht bereits mit exakt dem gleichen Namen vorhanden ist, und eventuell vorhandene ältere Dateien mit dem gleichen Namensmuster vorher löschen. Also immer die aktuelle Version davon verfügbar halten.
Die Reaktion ist merkwürdig:
- Der Parameter "$to_download" (erwartete Zielgröße) erhöht sich, als ob er die bisher heruntergeladene Größe darstellt.
- Der Parameter "$downloaded" (bisher heruntergeladene Größe) ist immer 0. (siehe erzeugte CSV-Logdatei)
- Die heruntergeladenen Daten werden nicht in die erzeugte Zieldatei gespeichert, sie bleibt leer.
- In einer vorherigen Abfrage konnte die erwartete Zielgröße problemlos bestimmt werden, sie wäre also nicht unbekannt.
- Wenn ich den übertragenen HTTP-Header ausgeben lasse, ist die Zielgröße darin lesbar.
Ich bin mir nicht sicher, ob ich etwas bei der Bearbeitung durcheinander gebracht habe, oder ob cURL hier die Progress-Callback-Funktion falsch bedient... aber warum?
PHP
<?php
header("Content-type: text/plain; charset=windows-1252");
global $next_percent;
global $next_tenth;
global $csv;
$urlpath = "http://webcdn.triongames.com/addons/assets/";
function file_get_contents_curl($url) # only for small files like the directory index
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_URL, $url);
$data = curl_exec($ch);
curl_close($ch);
return $data;
}
function file_get_size_curl($url)
{
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
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;
}
function progress($resource, $to_download, $downloaded, $to_upload=0, $uploaded=0)
{
global $next_percent;
global $next_tenth;
global $csv;
$percent = -1;
$tenth = -1;
fwrite($csv, "$to_download,$downloaded,$to_upload,$uploaded,$percent,$next_percent,$tenth,$next_tenth\r\n");
if($to_download > 0)
{
$percent = intval($downloaded * 100 / $to_download);
$tenth = intval($percent / 10);
if($tenth >= $next_tenth)
{
$next_tenth++;
$next_percent++;
echo " ".$tenth."0%\r\n";
}
else if($percent >= $next_percent)
{
$next_percent++;
echo ".";
}
flush();
}
flush();
}
echo "Getting directory content list from TRION assets archive... ";
$contents = file_get_contents_curl($urlpath);
flush();
if($contents === false)
{
die("ERROR: RIFT directory '$urlpath' not readable from TRION data server.\r\n");
}
echo "OK\r\nSearching current discoveries archive... ";
flush();
preg_match_all("|href=[\''](.*?)[\'']|", $contents, $_dirlist);
foreach($_dirlist[1] as $fname)
{
$fnmask = "Rift_Discoveries_*.zip";
if(fnmatch($fnmask, $fname))
{
echo "OK, found $fname\r\n";
flush();
if(file_exists($fname))
echo "Local file already exists.";
else
{
@array_map("unlink", glob($fnmask)); # delete all possibly left older archive files if a new current file was not yet cached
$rsize = file_get_size_curl($urlpath.$fname);
echo "Downloading $fname (".number_format($rsize, 0)." bytes):\r\n";
$next_tenth = 1;
$next_percent = 1;
$of = fopen($fname, "w+");
$csv = fopen("downloadlog.csv", "w+");
fwrite($csv, '"to download","downloaded","to_upload","uploaded","percent","next_percent","tenth","next_tenth"'."\r\n");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $urlpath.$fname); # remote source file to be downloaded
curl_setopt($ch, CURLOPT_FILE, $of); # write downloaded data to file
# curl_setopt($ch, CURLOPT_BUFFERSIZE, 8192);
# curl_setopt($ch, CURLOPT_TIMEOUT, 600);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, 'progress'); # callback
curl_setopt($ch, CURLOPT_NOPROGRESS, FALSE); # enable use of callback
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE); # do not write downloaded data to stdout
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); # follow possible redirects
curl_setopt($ch, CURLOPT_HEADER, FALSE); # do not write header to output file
curl_setopt($ch, CURLOPT_VERBOSE, TRUE); # debug, outputs header and possible download errors to stderr
$result = curl_exec($ch);
curl_close($ch);
fclose($of);
fclose($csv);
}
}
}
# ftp_close($ftp_stream);
echo "ERROR: No discoveries archive found.\r\n";
?>
Display More