当前位置:首页 > PHP

php如何实现下载进度

2026-02-14 04:47:33PHP

使用 cURL 获取下载进度

在 PHP 中,可以通过 cURL 的 CURLOPT_PROGRESSFUNCTIONCURLOPT_NOPROGRESS 选项来实现下载进度跟踪。需要启用进度回调函数并关闭默认的进度显示。

$url = 'https://example.com/largefile.zip';
$file = fopen('downloaded.zip', 'w');

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FILE, $file);
curl_setopt($ch, CURLOPT_NOPROGRESS, false);
curl_setopt($ch, CURLOPT_PROGRESSFUNCTION, function(
    $resource, $download_size, $downloaded, $upload_size, $uploaded
) {
    if ($download_size > 0) {
        $progress = round(($downloaded / $download_size) * 100, 2);
        echo "Progress: {$progress}%\n";
    }
});
curl_exec($ch);
curl_close($ch);
fclose($file);

使用输出缓冲实时显示进度

对于需要网页实时显示进度的情况,可以结合输出缓冲和 flush 函数。这种方法适用于浏览器端的进度显示。

ob_start();
$url = 'https://example.com/largefile.zip';
$file = fopen('downloaded.zip', 'w');

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_FILE => $file,
    CURLOPT_NOPROGRESS => false,
    CURLOPT_PROGRESSFUNCTION => function(
        $resource, $download_size, $downloaded, $upload_size, $uploaded
    ) {
        if ($download_size > 0) {
            $progress = round(($downloaded / $download_size) * 100, 2);
            echo "<script>updateProgress({$progress})</script>";
            ob_flush();
            flush();
        }
    }
]);
curl_exec($ch);
curl_close($ch);
fclose($file);
ob_end_clean();

分段下载与进度存储

对于大文件下载,可以考虑分段下载并将进度信息存储到数据库或文件中,以便中断后恢复下载。

php如何实现下载进度

$url = 'https://example.com/largefile.zip';
$file_path = 'downloaded.zip';
$progress_file = 'progress.json';

// 读取之前的进度
$progress = file_exists($progress_file) ? json_decode(file_get_contents($progress_file), true) : [
    'downloaded' => 0,
    'total_size' => 0
];

$ch = curl_init();
curl_setopt_array($ch, [
    CURLOPT_URL => $url,
    CURLOPT_RANGE => $progress['downloaded'] . '-',
    CURLOPT_WRITEFUNCTION => function($ch, $data) use ($file_path, $progress_file, &$progress) {
        $length = fwrite(fopen($file_path, 'a'), $data);
        $progress['downloaded'] += $length;

        if ($progress['total_size'] == 0) {
            $progress['total_size'] = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
        }

        file_put_contents($progress_file, json_encode($progress));
        return $length;
    }
]);
curl_exec($ch);
curl_close($ch);

使用 PHP 内置流包装器

PHP 的流包装器也可以用于实现简单的下载进度跟踪,虽然功能不如 cURL 全面。

$url = 'https://example.com/largefile.zip';
$context = stream_context_create([], [
    'notification' => function($notification_code, $severity, $message, $message_code, $bytes_transferred, $bytes_max) {
        if ($notification_code == STREAM_NOTIFY_PROGRESS && $bytes_max > 0) {
            $progress = round(($bytes_transferred / $bytes_max) * 100, 2);
            echo "Progress: {$progress}%\n";
        }
    }
]);

file_put_contents('downloaded.zip', fopen($url, 'r', false, $context));

结合 AJAX 实现网页进度显示

对于网页应用,可以结合前端 AJAX 和后端会话来实现实时进度显示。

php如何实现下载进度

后端 PHP (download.php):

session_start();
$url = 'https://example.com/largefile.zip';
$_SESSION['download_progress'] = ['total' => 0, 'current' => 0];

$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_FILE => fopen('downloaded.zip', 'w'),
    CURLOPT_NOPROGRESS => false,
    CURLOPT_PROGRESSFUNCTION => function($ch, $download_size, $downloaded, $upload_size, $uploaded) {
        $_SESSION['download_progress'] = [
            'total' => $download_size,
            'current' => $downloaded
        ];
    }
]);
curl_exec($ch);
curl_close($ch);

前端 JavaScript:

function checkProgress() {
    fetch('progress.php')
        .then(response => response.json())
        .then(data => {
            if (data.total > 0) {
                const progress = Math.round((data.current / data.total) * 100);
                document.getElementById('progress').innerText = `${progress}%`;
            }
            if (data.current < data.total) {
                setTimeout(checkProgress, 500);
            }
        });
}

// 开始下载
fetch('download.php').then(() => checkProgress());

进度检查接口 (progress.php):

session_start();
header('Content-Type: application/json');
echo json_encode($_SESSION['download_progress'] ?? ['total' => 0, 'current' => 0]);

分享给朋友:

相关文章

vue如何实现原理

vue如何实现原理

Vue 的核心实现原理 Vue 的核心原理主要包括响应式系统、虚拟 DOM、模板编译和组件化。以下分模块详细说明其实现机制。 响应式系统 Vue 2.x 使用 Object.defineProper…

vue如何实现拖动

vue如何实现拖动

Vue 实现拖动的常用方法 使用 HTML5 原生拖放 API HTML5 提供了原生的拖放 API,可以通过 draggable 属性和相关事件实现拖动功能。 <template>…

java如何实现异步

java如何实现异步

Java实现异步的方法 Java中实现异步编程可以通过多种方式,每种方式适用于不同的场景和需求。以下是常见的实现方法: 使用Thread类 创建新线程执行异步任务是最基础的方式。通过继承Thread…

vue如何实现404

vue如何实现404

实现 Vue 404 页面的方法 在 Vue 中实现 404 页面通常需要结合路由配置和动态路由匹配。以下是几种常见方法: 使用通配符路由匹配 在 Vue Router 配置中,可以通过 * 通配符…

vue如何实现拖拽

vue如何实现拖拽

实现拖拽的基本方法 在Vue中实现拖拽功能通常使用HTML5的Drag and Drop API或第三方库如vuedraggable。以下是两种方法的详细说明。 使用HTML5 Drag and D…

vue如何实现发票

vue如何实现发票

在Vue中实现发票功能通常需要结合前端展示、数据绑定和打印功能。以下是实现发票功能的关键步骤和代码示例: 发票模板设计 使用Vue的模板语法设计发票的HTML结构,结合CSS美化样式。发票模板通常包…