Skip to content

Instantly share code, notes, and snippets.

@ARACOOOL
Last active February 8, 2024 16:53
Show Gist options
  • Save ARACOOOL/0d9e5300b6d5b981dfad809af699d485 to your computer and use it in GitHub Desktop.
Save ARACOOOL/0d9e5300b6d5b981dfad809af699d485 to your computer and use it in GitHub Desktop.
Download remote file with progress bar (PHP, curl)
#!/usr/bin/php
<?php
/**
* Usage:
* php downloader.php http://path.to/remote/file.ext /local/file/path
*
* Output:
* [############################################################################################### ] 96%
*/
/**
* Class Downloader
*/
class Downloader
{
/**
* @var string
*/
private $url;
/**
* @var string
*/
private $destination;
/**
* Downloader constructor.
* @param string $url
* @param string $destination
*/
public function __construct(string $url, string $destination)
{
$this->url = $this->prepareUrl($url);
$this->destination = $this->prepareDestination($destination);
}
/**
* @param string $url
* @return string
*/
private function prepareUrl(string $url): string
{
if (!filter_var($url, FILTER_VALIDATE_URL)) {
$this->stderr('Invalid URL');
die;
}
return $url;
}
/**
* @param string $output
*/
private function stderr(string $output): void
{
fwrite(STDERR, $output);
}
/**
* @param string $destination
* @return string
*/
private function prepareDestination(string $destination): string
{
$fileName = basename($destination);
$dirName = realpath(dirname($destination));
if (!$dirName) {
$this->stderr('Check the destination path of file');
die;
}
return $dirName . DIRECTORY_SEPARATOR . $fileName;
}
/**
*
*/
public function download(): void
{
$ch = curl_init();
$fp = fopen($this->destination, 'wb');
curl_setopt_array($ch, [
CURLOPT_URL => $this->url,
CURLOPT_HEADER => false,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_FILE => $fp,
CURLOPT_PROGRESSFUNCTION => [$this, 'progress'],
CURLOPT_NOPROGRESS => false,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_FAILONERROR => true
]);
curl_exec($ch);
if (curl_errno($ch)) {
$this->stderr('Error: ' . curl_error($ch));
die;
}
curl_close($ch);
fclose($fp);
}
/**
* @param $resource
* @param int $download_size
* @param int $downloaded
* @param int $upload_size
* @param int $uploaded
*/
private function progress($resource, $download_size = 0, $downloaded = 0, $upload_size = 0, $uploaded = 0): void
{
$percent = $download_size > 0 && $downloaded > 0 ? ceil($downloaded * 100 / $download_size) : 0;
$this->stdout('[' . str_pad('', $percent, '#') . str_pad('', 100 - $percent) . "] $percent%\r");
}
/**
* @param string $output
*/
private function stdout(string $output): void
{
fwrite(STDOUT, $output);
}
}
$dw = new Downloader($argv[1], $argv[2]);
$dw->download();
@ardzz
Copy link

ardzz commented Oct 2, 2020

how to calculate current speeds?

@ARACOOOL
Copy link
Author

ARACOOOL commented Oct 3, 2020

how to calculate current speeds?

The app does not do it, but you can calculate it separately:
$downloadSize = 15360; // kb
$downloadTime = 2000; // milliseconds

$estimatedDwnSpeed = $downloadSize / $downloadTime = 7.6; // mbps

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment