You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用PHP分块下载大文件?服务器限单文件≤4MB

PHP实现无JS自动分块下载大文件(规避4MB下载限制)

我明白你的场景:服务器拦截超过4MB的下载请求,只能用PHP实现自动刷新分块下载,且工作环境不支持JavaScript。你的原代码核心问题出在分块计数逻辑错误、请求头设置不当,以及没有向客户端返回正确的分块响应标识,导致浏览器无法识别续传逻辑,也没法触发后续自动刷新。

下面是修正后的完整代码,我会逐一解释关键修复点:

<?php
session_start();
ini_set('max_execution_time', 0);

// 获取目标文件URL
$url = $_GET['url'] ?? '';
if (empty($url)) {
    die('请提供要下载的文件URL');
}

// 计算文件总大小,增强兼容性
function getFileSize($url) {
    if (str_starts_with($url, 'http')) {
        $headers = array_change_key_case(get_headers($url, 1), CASE_LOWER);
        // 处理重定向后的Content-Length(如果存在多值情况)
        if (isset($headers['content-length'])) {
            return is_array($headers['content-length']) ? end($headers['content-length']) : $headers['content-length'];
        }
        // 若直接获取失败,用HEAD请求重试
        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_NOBODY, true);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
        curl_exec($ch);
        $size = curl_getinfo($ch, CURLINFO_CONTENT_LENGTH_DOWNLOAD);
        curl_close($ch);
        return $size;
    } else {
        return @filesize($url);
    }
}

$fileTotalSize = getFileSize($url);
if (!$fileTotalSize) {
    die('无法获取目标文件大小');
}

// 分块大小:3.999MB(比4MB限制小1字节)
$chunkSize = (4 * 1024 * 1024) - 1;

// 初始化session中的下载偏移量
if (!isset($_SESSION['currentOffset'])) {
    $_SESSION['currentOffset'] = 0;
}

$currentOffset = $_SESSION['currentOffset'];
// 计算当前分块的结束位置(避免超出文件总大小)
$endOffset = min($currentOffset + $chunkSize, $fileTotalSize - 1);
$rangeHeader = "bytes=$currentOffset-$endOffset";

// 用CURL请求目标分块内容
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36');
curl_setopt($ch, CURLOPT_BINARYTRANSFER, true);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 0);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 0);
// 仅向目标服务器发送Range请求头,原代码错误混入了响应头
curl_setopt($ch, CURLOPT_HTTPHEADER, array($rangeHeader));
curl_setopt($ch, CURLOPT_HEADER, false);

$chunkContent = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode !== 206 && $httpCode !== 200) {
    die("分块请求失败,HTTP状态码:$httpCode");
}

// 向客户端返回响应头,区分首次下载与续传
if ($currentOffset === 0) {
    // 首次请求,设置下载文件的基础头信息
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename=' . basename(parse_url($url, PHP_URL_PATH)));
    header('Content-Transfer-Encoding: binary');
    header('Connection: Keep-Alive');
    header('Expires: 0');
    header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
    header('Pragma: public');
}

// 设置分块响应标识,让浏览器识别这是续传内容
header("HTTP/1.1 206 Partial Content");
header("Accept-Ranges: bytes");
header("Content-Range: bytes $currentOffset-$endOffset/$fileTotalSize");
header("Content-Length: " . strlen($chunkContent));

// 输出当前分块内容并强制刷新缓冲区
echo $chunkContent;
flush();
ob_flush();

// 更新session中的下载偏移量
$_SESSION['currentOffset'] = $endOffset + 1;

// 判断是否需要继续下载下一个分块
if ($_SESSION['currentOffset'] < $fileTotalSize) {
    // 立即刷新当前页面,继续下载下一块
    header("Refresh: 0; url=" . $_SERVER['REQUEST_URI']);
} else {
    // 下载完成,销毁session释放资源
    session_destroy();
    session_write_close();
}
?>

关键修复点说明:

  1. 分块计数逻辑修正:用currentOffset记录当前下载的起始位置,每次下载后更新为endOffset + 1,彻底避免了原代码中模运算的优先级错误。
  2. 请求头与响应头分离:原代码错误地在CURL请求中混入了响应头(HTTP/1.1 206 Partial Content),现在仅向目标服务器发送Range请求头,206相关头是返回给客户端的响应标识。
  3. 客户端响应优化:返回Content-Range头让浏览器识别这是分块下载的一部分,部分浏览器/下载工具可以自动续传合并分块。
  4. 文件大小获取增强:处理了重定向场景下的多值Content-Length,并增加HEAD请求重试逻辑,提升兼容性。
  5. 刷新逻辑适配性:用$_SERVER['REQUEST_URI']自动获取当前请求地址,避免硬编码URL,适配不同部署环境。

使用注意事项:

  • 确保服务器开启Session支持,且Session存储目录有写入权限。
  • 目标服务器必须支持Range请求(大部分现代服务器都支持),否则分块下载无法工作。
  • 由于每次刷新都是独立请求,部分浏览器可能会弹出多次下载提示,建议使用专业下载管理器来自动合并分块。

内容的提问来源于stack exchange,提问作者Rakib Hasan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:24:21