使用SFTP上传文件

43
我已成功通过FTP上传文件,但现在需要通过SFTP来完成。我可以成功连接到远程服务器,创建文件并将其写入,但是我无法将本地服务器上的现有文件上传到远程服务器。ftp_put函数是否不适用于SFTP连接?
我的代码用于写入文件:
//Send file via sftp to server

$strServer = "*****";
$strServerPort = "****";
$strServerUsername = "*****";
$strServerPassword = "*****";
$csv_filename = "Test_File.csv";

//connect to server
$resConnection = ssh2_connect($strServer, $strServerPort);

if(ssh2_auth_password($resConnection, $strServerUsername, $strServerPassword)){
    //Initialize SFTP subsystem

    echo "connected";
    $resSFTP = ssh2_sftp($resConnection);    

    $resFile = fopen("ssh2.sftp://{$resSFTP}/".$csv_filename, 'w');
    fwrite($resFile, "Testing");
    fclose($resFile);                   

}else{
    echo "Unable to authenticate on server";
}

有人能否成功地通过像上面提到的sftp方式抓取本地文件并进行上传?如有示例将不胜感激。

谢谢


1
你为什么把它叫做 resFile?为什么是“res”?它代表什么? - Black
结果我猜是.. @Black - denns
你在代码中哪里使用了 $strServerPassword?我没有看到它被使用在这里。 - FerdousTheWebCoder
5个回答

54

使用上述方法(涉及sftp),您可以使用stream_copy_to_stream

$resFile = fopen("ssh2.sftp://{$resSFTP}/".$csv_filename, 'w');
$srcFile = fopen("/home/myusername/".$csv_filename, 'r');
$writtenBytes = stream_copy_to_stream($srcFile, $resFile);
fclose($resFile);
fclose($srcFile);

你也可以尝试使用ssh2_scp_send


1
那个完美地运行了,谢谢。我会为将来的项目做个书签! - Marc
1
这很棒,但不要忘记为用户禁用open_basedir。 - Phd. Burak Öztürk

33

就我个人而言,我更喜欢避免使用PECL SSH2扩展。我的首选方法包括phpseclib,一个纯PHP SFTP实现。以下是一个使用phpseclib 2.0的示例(需要composer):

<?php
require __DIR__ . '/vendor/autoload.php';

use phpseclib\Net\SFTP;

$sftp = new SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

$sftp->put('remote.ext', 'local.ext', SFTP::SOURCE_LOCAL_FILE);
?>

下面是使用phpseclib 1.0的同一示例:

<?php
include('Net/SFTP.php');

$sftp = new Net_SFTP('www.domain.tld');
if (!$sftp->login('username', 'password')) {
    exit('Login Failed');
}

$sftp->put('remote.ext', 'local.ext', NET_SFTP_LOCAL_FILE);
?>

我对phpseclib比PECL扩展更喜欢的一个重要原因是它具有可移植性。也许PECL扩展在某个Linux版本上可以工作,但在另一个版本上却无法正常工作。而且,在共享主机上几乎从不安装,因此几乎无法使用。

出人意料的是,phpseclib也更快。如果您需要确认已上传的文件,则可以使用phpseclib的内置日志作为证明。


我正在使用上面的脚本上传一些csv文件,但是我遇到了以下错误:Net\SSH2.php的第3521行超过了120秒的最大执行时间,我该如何超过它。 - Anand Mishra

17

对我而言,这个方法可行:

$connection = ssh2_connect($server, $serverPort);

if(ssh2_auth_password($connection, $serverUser, $serverPassword)){
    echo "connected\n";
    ssh2_scp_send($connection, "/path/to/local/".$file, "/path/to/remote/".$file);
    echo "done\n";
} else {
    echo "connection failed\n";
}

不过,我首先需要安装libssh2-php:

sudo apt-get install libssh2-php

4
我得到了“libssh2-php包不可用”的提示,因此请使用“sudo apt-get install php-ssh2”代替。 - omega1

4

针对纯PHP SFTP实现的简单文档,请参考以下链接:

使用PHP通过SFTP上传文件

文件夹结构如下:

Main Folder->
    my-files(Contain File Which Transfer To Remote Server)
    phpseclib0.3.0
    sftp.php

1
分享更多的信息,发现当从 Linux (64 位) 复制文件到 Windows (32 位) 时,ssh2_scp_send 没有正确复制(字节不同),但 sftp 例程完美运行。在使用 Windows 进行 sftp 时,如果在 C:\to\path 的情况下需要使用 ssh2.sftp://{$resSFTP}/cygdrive/c/to/path,如果在 Windows 计算机上使用 Cygwin 进行 SSH。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接