当前位置:首页 > PHP

php怎么实现下载

2026-01-28 23:28:11PHP

实现文件下载的基本方法

在PHP中实现文件下载通常通过设置HTTP头信息强制浏览器触发下载行为。核心代码如下:

$file_path = '/path/to/file.pdf';
$file_name = 'document.pdf';

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file_name).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file_path));
readfile($file_path);
exit;

处理大文件下载

对于大文件下载需要优化内存使用,避免直接读取整个文件:

$chunk_size = 1024 * 1024; // 1MB chunks
$handle = fopen($file_path, 'rb');
while (!feof($handle)) {
    echo fread($handle, $chunk_size);
    ob_flush();
    flush();
}
fclose($handle);

安全下载控制

为防止目录穿越攻击,应对文件路径进行验证:

$base_dir = '/safe/download/directory/';
$requested_file = $_GET['file'];
$real_path = realpath($base_dir . $requested_file);

if ($real_path === false || strpos($real_path, $base_dir) !== 0) {
    die('Invalid file path');
}

断点续传支持

实现HTTP Range请求支持断点续传:

$file_size = filesize($file_path);
$start = 0;
$end = $file_size - 1;

if (isset($_SERVER['HTTP_RANGE'])) {
    preg_match('/bytes=(\d+)-(\d+)?/', $_SERVER['HTTP_RANGE'], $matches);
    $start = (int)$matches[1];
    $end = isset($matches[2]) ? (int)$matches[2] : $file_size - 1;

    header('HTTP/1.1 206 Partial Content');
    header('Content-Range: bytes '.$start.'-'.$end.'/'.$file_size);
}

header('Accept-Ranges: bytes');
header('Content-Length: '.($end - $start + 1));

$handle = fopen($file_path, 'rb');
fseek($handle, $start);

下载统计与限速

添加下载统计和速度限制功能:

$speed_limit = 1024 * 50; // 50KB/s
$start_time = microtime(true);
$bytes_sent = 0;

while (!feof($handle) && connection_status() == 0) {
    $buffer = fread($handle, $speed_limit);
    echo $buffer;
    $bytes_sent += strlen($buffer);

    $elapsed = microtime(true) - $start_time;
    $should_take = $bytes_sent / $speed_limit;
    if ($elapsed < $should_take) {
        usleep(($should_take - $elapsed) * 1000000);
    }

    ob_flush();
    flush();
}

常见问题处理

处理文件名编码问题:

php怎么实现下载

$user_agent = $_SERVER['HTTP_USER_AGENT'];
$encoded_filename = rawurlencode($file_name);

if (preg_match('/MSIE|Trident/i', $user_agent)) {
    header('Content-Disposition: attachment; filename="'.iconv('UTF-8', 'CP932//IGNORE', $file_name).'"');
} elseif (preg_match('/Firefox/i', $user_agent)) {
    header('Content-Disposition: attachment; filename*=UTF-8\'\''.$encoded_filename);
} else {
    header('Content-Disposition: attachment; filename="'.$file_name.'"');
}

标签: php
分享给朋友:

相关文章

php记住密码怎么实现

php记住密码怎么实现

使用Cookie实现记住密码功能 在PHP中,可以通过设置Cookie来记住用户的登录状态。以下是一个简单的实现方式: // 用户登录验证成功后 if ($login_success) {…

php实现的分页

php实现的分页

PHP 实现分页的方法 基本分页逻辑 分页的核心在于计算总页数、当前页码以及数据偏移量。假设每页显示 10 条数据: $current_page = isset($_GET['page']) ? (…

php 实现秒杀

php 实现秒杀

PHP 实现秒杀的关键技术 秒杀系统需要解决高并发、超卖、性能瓶颈等问题。以下是实现秒杀的核心方案: 使用 Redis 预减库存 将商品库存提前加载到 Redis 中,通过原子操作保证库存准确性:…

php实现下载

php实现下载

PHP实现文件下载 使用PHP实现文件下载可以通过设置HTTP头部信息强制浏览器下载文件而非直接打开。以下是几种常见的方法: 方法一:直接输出文件内容 $file_path = 'path/to/…

php 实现类

php 实现类

PHP 类的基本实现 在 PHP 中,类通过 class 关键字定义,后跟类名和一对花括号。类名通常遵循大驼峰命名法(如 ClassName)。以下是基本语法: class ClassName {…

php 实现单点登录

php 实现单点登录

PHP 实现单点登录的方法 单点登录(SSO)允许用户通过一次登录访问多个相互信任的系统。以下是基于 PHP 的实现方案: 基于共享 Session 的方案 在同一个主域名下的子域名间可以通过共享…