📅  最后修改于: 2023-12-03 14:43:46.683000             🧑  作者: Mango
在 Laravel 开发中,我们经常需要实现文件下载的功能。而有些文件可能会比较大,因此需要考虑到下载进度的显示。在本文中,我们将介绍如何使用 Laravel 和进度条库来实现带有进度条的文件下载功能。
我们可以使用 Symfony Progress Bar 来实现进度条的功能。由于 Laravel 默认使用 Composer 管理依赖,因此我们可以使用 Composer 来安装进度条库。在 Laravel 项目根目录下运行以下命令:
composer require symfony/console
composer require symfony/progress-bar
在下载文件之前,我们需要确保文件存储在服务器上。首先,我们需要为文件创建一个存储路径,可以在 config/filesystems.php
文件中配置:
'disks' => [
// ...
'downloads' => [
'driver' => 'local',
'root' => public_path('downloads'),
],
// ...
],
在上面的配置中,我们创建了一个名为 downloads
的磁盘,它的驱动类型是本地存储,并指定了文件保存的根目录为 public/downloads
。接下来,我们可以将文件保存到该磁盘中:
use Illuminate\Support\Facades\Storage;
$url = 'https://example.com/large_file.zip';
$fileName = 'large_file.zip';
Storage::disk('downloads')->put($fileName, file_get_contents($url));
在上面的代码中,我们使用了 Laravel 的 Storage
门面和 file_get_contents
函数,将文件从远程服务器下载到本地,并保存到我们之前创建的 downloads
磁盘中。
现在,我们已经可以下载文件并将其保存到磁盘中了。接下来,我们将添加进度条来显示下载进度。要使用进度条,我们需要在控制台中输出进度条信息,在 Laravel 中我们可以使用 Symfony Console
组件的控制台类来实现。在控制台输出进度条时,我们需要知道下载的文件大小以及已下载的文件大小。我们可以使用 PHP 的 filesize
函数来获取文件大小。
use Symfony\Component\Console\Helper\ProgressBar;
$fileSize = Storage::disk('downloads')->size($fileName);
$progressBar = new ProgressBar($this->output, $fileSize);
$progressBar->start();
$bytesWritten = 0;
Storage::disk('downloads')->getDriver()->readStream($fileName);
while (!feof($stream)) {
$buffer = fread($stream, 1024);
$bytesWritten += strlen($buffer);
$progressBar->setProgress($bytesWritten);
}
$progressBar->finish();
在上面的代码中,我们使用 Storage
的 readStream
方法来获得一个可以读取文件的流对象,之后我们通过循环读取文件内容,并将已下载的文件大小传递给进度条对象,进度条就可以动态地显示下载的进度情况了。最后,我们需要手动调用 finish
方法结束进度条的显示。
下面是完整的代码实现,请仔细阅读并调整其中的路径等参数以适应您的项目:
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Helper\ProgressBar;
class DownloadFileCommand extends Command
{
protected $signature = 'download:file {url} {fileName}';
protected $description = 'Download a file with progress bar.';
public function handle()
{
$url = $this->argument('url');
$fileName = $this->argument('fileName');
$fileSize = $this->getFilesize($url);
$progressBar = new ProgressBar($this->output, $fileSize);
$progressBar->start();
$bytesWritten = 0;
$stream = fopen($url, 'r');
Storage::disk('downloads')->put($fileName, $stream);
$stream = Storage::disk('downloads')->getDriver()->readStream($fileName);
while (!feof($stream)) {
$buffer = fread($stream, 1024);
$bytesWritten += strlen($buffer);
$progressBar->setProgress($bytesWritten);
}
$progressBar->finish();
fclose($stream);
$this->info(PHP_EOL.'File '.$fileName.' downloaded!');
}
protected function getFilesize($url)
{
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_HEADER, true);
curl_setopt($curl, CURLOPT_NOBODY, true);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
$header = curl_exec($curl);
curl_close($curl);
$size = null;
preg_match('/Content-Length:\s*(\d+)/i', $header, $matches);
if (isset($matches[1])) {
$size = (int) $matches[1];
}
return $size;
}
}
在本文中,我们介绍了如何使用 Laravel 和进度条库来实现带有进度条的文件下载功能。通过实现该功能,我们可以更加详细地了解 Laravel 的文件存储和控制台操作,并且可以为我们的应用程序添加更加友好的体验。