0

您好我正在使用以下代码将一个大文件(500MB)上传到 sftp 服务器。

<?php

$connection = ssh2_connect($this->host, $this->port, null);
$sftp = ssh2_sftp($connection);

$connection_string = ((int) $sftp) . $remotePath . $remoteFilename;
$stream = fopen('ssh2.sftp://' . $connection_string, 'w');
$source = fopen($localFilepath, 'r');

if (!$stream) {
    throw new Exception('Could not create file: ' . $connection_string);
}

while (!feof($source)) {
    // Chunk size 32 MB
    if (fwrite($stream, fread($source, 33554432)) === false) {
        throw new Exception('Could not send data: ' . $connection_string);
    }
}

fclose($source);
fclose($stream);

但是上传速度慢。代码在 Google Cloud Run 上运行。上传速度约为 8 MiB/s。

我也尝试通过 shell_exec 使用 lftp,但这会导致由于 Cloud Run 的更多问题。

上行链路不是问题,因为我可以通过 CURL post 发送文件而没有任何问题。

任何人都可以在这里提供帮助吗?

非常感谢,最好的,intxcc

4

1 回答 1

3

问题是即使 32MB 被读取然后写入 sftp 流,fwrite 也会以不同的大小进行分块。我想只有几KB。

对于文件系统(这是 fwrite 的常见情况),这很好,但由于写入远程服务器而导致的高延迟不会。

所以解决方案是增加 sftp 流的块大小

stream_set_chunk_size($stream, 1024 * 1024);

所以最终的工作代码是:

<?php

$connection = ssh2_connect($this->host, $this->port, null);
$sftp = ssh2_sftp($connection);

$connection_string = ((int) $sftp) . $remotePath . $remoteFilename;
$stream = fopen('ssh2.sftp://' . $connection_string, 'w');
$source = fopen($localFilepath, 'r');

// Stream chunk size 1 MB
stream_set_chunk_size($stream, 1024 * 1024);

if (!$stream) {
    throw new Exception('Could not create file: ' . $connection_string);
}

while (!feof($source)) {
    // Chunk size 32 MB
    if (fwrite($stream, fread($source, 33554432)) === false) {
        throw new Exception('Could not send data: ' . $connection_string);
    }
}

fclose($source);
fclose($stream);

希望这有助于下一个白发的人试图弄清楚这一点;)

于 2020-11-03T18:57:59.013 回答