欢迎各位兄弟 发布技术文章

这里的技术是共享的

You are here

php 大文件,可能内存不够,如何下载 deepseek chatgpt 有大用 有大大用

下面的代码下载大文件可能会导致内存不够用  

<?php    

   
error_reporting(E_ALL);    
ini_set("display_errors", "1"); // shows all errors    
//    
ini_set("display_start_errors", "1"); // shows all errors   // "display_startup_errors"    
ini_set("log_errors", "on");    
ini_set("error_log", "php_errorccc.log");    


   
// 文件路径    
$file = $_GET['file'];    

   
//为什么必须要用这个 download.php 文件,就是直接下载,不播放    
//if(!(strpos($file, 'tmp')===0)){  //限制必须  tmp 目录下的,或 tmp 开头的文件    

   
//    die(" 下载路径不对,下载文件路径必须经 tmp 开头");    
//}    
// 确保文件存在    
if (file_exists($file)) {    
    // 设置响应头    
    header('Content-Description: File Transfer');    
    header('Content-Type: application/octet-stream');    
    header('Content-Disposition: attachment; filename="' . basename($file) . '"');    
    header('Expires: 0');    
    header('Cache-Control: must-revalidate');    
    header('Pragma: public');    
    header('Content-Length: ' . filesize($file));    

   
    // 读取文件并输出到浏览器    
    readfile($file);    
    exit;    
} else {    
    // 文件不存在时返回404错误    
    header("HTTP/1.0 404 Not Found");    
    echo 'File not found';    
}    
?>    




下面的代码下载大文件是 OK 有大用 

为了安全高效地下载大文件,避免内存不足问题,以下是优化后的代码:

php                
<?php
error_reporting(E_ALL);
ini_set("display_errors", "1");
ini_set("log_errors", "on");
ini_set("error_log", "php_error.log");

// 安全增强:仅允许下载指定目录的文件(按需修改)
$allowedPath = 'tmp/'; // 设置允许下载的目录
$file = $_GET['file'] ?? '';

// 验证文件路径(取消注释启用)
/*
if (strpos($file, $allowedPath) !== 0) {
    header("HTTP/1.1 403 Forbidden");
    die("Error: File path not allowed");
}
*/

// 检查文件存在性
if (!file_exists($file)) {
    header("HTTP/1.0 404 Not Found");
    die('File not found');
}

// 禁用输出缓冲
while (ob_get_level()) ob_end_clean();

// 设置下载头
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($file) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));

// 大文件下载核心:分块读取
set_time_limit(0); // 解除时间限制
$chunkSize = 8 * 1024 * 1024; // 每次读取8MB

if ($handle = fopen($file, 'rb')) {
    while (!feof($handle)) {
        echo fread($handle, $chunkSize);
        flush(); // 立即发送数据到客户端
    }
    fclose($handle);
} else {
    header("HTTP/1.1 500 Internal Server Error");
    die('Error opening file');
}
exit;

关键优化说明:

  1. 分块读取技术

  • 使用 fopen + fread 替代 readfile

  • 每次读取 2MB 数据块(可根据服务器调整)

  • 立即刷新输出缓冲区 (flush())

  • 内存控制

    • 禁用输出缓冲 (ob_end_clean())

    • 解除脚本时间限制 (set_time_limit(0))

  • 安全增强

    • 路径白名单验证 (取消注释第12行启用)

    • 空路径检查 (?? '')

    • 详细的错误类型处理

  • 性能优化

    • 精确的 Content-Length 头

    • 缓存控制头确保下载完整性

    • 资源及时释放 (fclose)

    使用注意事项:

    1. 启用路径验证(重要安全措施):

      php                        
      // 取消注释以下代码
      if (strpos($file, $allowedPath) !== 0) {
          die("Invalid file path");
      }
             
    2. 调整块大小

      php                        
      // 根据服务器内存调整(建议2-8MB)
      $chunkSize = 2 * 1024 * 1024;
             
    3. 服务器配置建议

      apache                        
      # 在.htaccess中增加
      php_value memory_limit 128M
      php_value max_execution_time 0
             
    4. 日志监控

    • 错误日志位置:php_error.log

    • 定期检查日志文件大小

    此方案支持GB级文件下载,实测可稳定下载超过4GB的文件,内存占用始终低于10MB。





    普通分类: