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

Laravel SFTP驱动下载大文件报错Error reading channel data (7)

问题描述

使用Laravel + Flysystem SFTP驱动下载大文件(耗时超1分钟)时,抛出错误:Error reading channel data (7)。已尝试以下操作但无效:

  • 调整SFTP配置中的timeout和useAgent参数
  • 提前初始化流对象、改用get()方法加载文件到内存
  • 在Sail容器中挂载添加ServerAliveInterval的ssh_config

使用scp或FileZilla可正常下载目标文件,依赖版本如下:

  • laravel/framework@v11.2.0
  • laravel/sail@v1.29.1
  • league/filesystem@3.27.0
  • league/flysystem-sftp-v3@3.26.0

核心代码:

Storage::disk('local')->writeStream(
    "sftp/{$localFilename}",
    Storage::disk('sftp')->readStream($remoteFilePath)
);

解决方案

1. 在SFTP配置中添加SSH存活保活参数

PHP的ssh2扩展默认不读取系统ssh_config,需在Laravel的文件系统配置中直接指定SSH会话的保活选项:

修改config/filesystems.php的sftp磁盘配置:

'sftp' => [
    'driver' => 'sftp',
    'host' => env('SFTP_HOST'),
    'username' => env('SFTP_USERNAME'),
    'password' => env('SFTP_PASSWORD'),
    'timeout' => 300, // 整体超时设为5分钟(根据文件大小调整)
    'connectTimeout' => 60, // 连接超时设为1分钟
    'config' => [
        'ssh2.server_alive_interval' => 30, // 每30秒发送一次保活包
        'ssh2.server_alive_count_max' => 10, // 连续10次无响应才断开连接
    ],
],

2. 分块处理流读写

避免直接传递完整流导致连接长时间无交互,手动分块读取写入:

$remoteStream = Storage::disk('sftp')->readStream($remoteFilePath);
$localPath = "sftp/{$localFilename}";
$localStream = Storage::disk('local')->writeStream($localPath, fopen('php://temp', 'w+b'));

$chunkSize = 8192; // 每次读取8KB块,可根据服务器带宽调整
while (!feof($remoteStream)) {
    $chunk = fread($remoteStream, $chunkSize);
    fwrite($localStream, $chunk);
    fflush($localStream); // 立即写入磁盘,避免缓冲区积压
}

// 关闭流释放资源
fclose($remoteStream);
fclose($localStream);

3. 手动创建SSH会话并配置参数

如果上述配置仍不生效,可手动创建SSH会话并传入Flysystem适配器,精准控制连接参数:

在AppServiceProvider的boot方法中添加自定义磁盘扩展:

use Illuminate\Support\Facades\Storage;
use League\Flysystem\Filesystem;
use League\Flysystem\PhpseclibV3\SftpAdapter;
use League\Flysystem\PhpseclibV3\SftpConnectionProvider;
use Illuminate\Filesystem\FilesystemAdapter;

public function boot()
{
    Storage::extend('sftp_custom', function ($app, $config) {
        // 创建SSH连接并设置保活参数
        $session = ssh2_connect(
            $config['host'],
            $config['port'] ?? 22,
            [
                'timeout' => 300,
                'ssh2.server_alive_interval' => 30,
                'ssh2.server_alive_count_max' => 10,
            ]
        );

        ssh2_auth_password($session, $config['username'], $config['password']);

        // 创建SFTP适配器
        $adapter = new SftpAdapter(
            new SftpConnectionProvider(fn () => $session),
            $config['root'] ?? ''
        );

        return new FilesystemAdapter(
            new Filesystem($adapter),
            $adapter
        );
    });
}

然后在.env中配置sftp_custom的参数,代码中使用Storage::disk('sftp_custom')进行文件操作。

4. 升级PHP ssh2扩展版本

旧版本的ssh2扩展可能存在大文件传输的bug,在Sail容器中执行以下命令升级:

pecl install ssh2-1.4.1 # 安装最新稳定版

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 00:07:49