【问题标题】:transfer file through SFTP通过 SFTP 传输文件
【发布时间】:2015-08-04 12:50:37
【问题描述】:

我想通过 SFTP 传输文件。我发现了how to transfer a file through SFTP in java? 提出的类似问题。我从本地主机上的帖子中尝试了建议的解决方案。但我在输出下显示以下错误。

输出

preparing the host information for sftp.
Host connected.
sftp channel opened and connected.
2: No such file
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2846)
at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2340)
at com.jcraft.jsch.ChannelSftp.cd(ChannelSftp.java:342)
at ScpTo.main(ScpTo.java:69)
File transfered successfully to host.
sftp Channel exited.
Channel disconnected.
Host Session disconnected.

代码

import java.io.File;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

public class ScpTo {

    /**
     *
     */
    public ScpTo() {
        // TODO Auto-generated constructor stub
    }

    /**
     * @param args
     */
    public static void main(String[] args) {
         String SFTPHOST = "192.168.1.3";
            int SFTPPORT = 22;
            String SFTPUSER = "sam-PC";
            String SFTPPASS = "";
            String SFTPWORKINGDIR = "C:/Users/sam/Desktop/hi.txt";

            Session session = null;
            Channel channel = null;
            ChannelSftp channelSftp = null;
            System.out.println("preparing the host information for sftp.");

                JSch jsch = new JSch();
                try {
                    session = jsch.getSession(SFTPUSER, SFTPHOST, SFTPPORT);
                } catch (JSchException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                session.setPassword(SFTPPASS);
                java.util.Properties config = new java.util.Properties();
                config.put("StrictHostKeyChecking", "no");
                session.setConfig(config);
                try {
                    session.connect();
                } catch (JSchException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("Host connected.");
                try {
                    channel = session.openChannel("sftp");
                } catch (JSchException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                try {
                    channel.connect();
                } catch (JSchException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("sftp channel opened and connected.");
                channelSftp = (ChannelSftp) channel;
                try {
                    channelSftp.cd(SFTPWORKINGDIR);
                } catch (SftpException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                File f = new File(SFTPWORKINGDIR);
                try {
                    channelSftp.put(new FileInputStream(f), f.getName());
                } catch (FileNotFoundException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (SftpException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("File transfered successfully to host.");


                channelSftp.exit();
                System.out.println("sftp Channel exited.");
                channel.disconnect();
                System.out.println("Channel disconnected.");
                session.disconnect();
                System.out.println("Host Session disconnected.");

    }
}

【问题讨论】:

  • not 立即捕获所有异常开始。在寻求帮助之前,先了解自己想要做什么,自己缩小问题范围。
  • 帖子已更新。这似乎是 session.connect() 的问题;
  • 服务器启动了吗?尝试运行netstat -ano并检查是否有进程在监听22端口。
  • @龙华。我会试试看。感谢您的建议
  • 尝试使用任何其他客户端(如 FireFox + FireFTP)首先访问 localhost:22。

标签: java sftp jsch


【解决方案1】:

堆栈跟踪显示错误发生在执行 cd 命令期间。报错是“no such file”,实际上可能是“no such directory”的意思,所以问题几乎可以肯定是SFTPWORKINGDIR定义的目录不存在。

不过,我不怪你感到困惑。该 API 似乎非常复杂。我是edtFTPj/PRO 的开发者之一,它提供了一个更简单的界面。例如,下面是通过 SFTP 下载文件的代码:

SecureFileTransferClient client = new SecureFileTransferClient();
client.setProtocol(Protocol.SFTP);
client.setRemoteHost("myserver.com");
client.setUserName("myusername");
client.setPassword("mypassword");
client.connect();
client.downloadFile("filename.txt", "filename.txt");
client.disconnect();

请注意,edtFTPj/PRO 不是免费产品。

【讨论】:

    【解决方案2】:
    String SFTPWORKINGDIR = "C:/Users/sam/Desktop/hi.txt";
    ...
    channelSftp.cd(SFTPWORKINGDIR);
    

    首先,SFTPWORKINGDIR 似乎指的是文件,而不是目录。您可能正在尝试 cd 到某个文件,或者应该是一个文件。

    其次,SFTP 使用类似 unix 的路径名模型。以“/”开头的路径名是绝对路径,从服务器的根目录解析。不以“/”开头的路径是相对路径,从您的 SFTP 会话开始的目录(通常是您在服务器上登录的帐户的主目录)解析。

    SFTPWORKINGDIR 的值是 windows 格式的路径,而不是 unix 格式的路径。即使 SFTP 服务器在 Windows 系统上运行,SFTP 服务器也很可能没有按照您的意愿解释它。您应该查阅 SFTP 服务器的文档并将路径名转换为正确的格式以访问您想要的目录。如果 SFTP 服务器是 Cygwin openssh 服务器,我相信正确的形式应该是“/cygdrive/c/Users/sam/Desktop”。

    【讨论】:

      【解决方案3】:

      这是一个完整的“上传代码”,带有从 Windows 机器到 linux 机器的身份验证。此代码从您的机器(win)从特定位置上传文件并上传到 FTP 服务器。这是我为我的问题申请的解决方案。如果有人看到问题,请发表评论。

      try {
              JSch jsch = new JSch();
              Session session = jsch.getSession( "<userName>", "<ip_block>", 22 );
              session.setConfig( "PreferredAuthentications", "password" );
              session.setPassword( "<pasword>" );
              java.util.Properties config = new java.util.Properties(); 
              config.put("StrictHostKeyChecking", "no");//do not prefer this. demo only
              session.setConfig(config);
              session.connect( 1200 );
              Channel channel = session.openChannel( "sftp" );
              ChannelSftp sftp = ( ChannelSftp ) channel;
              sftp.connect( 600 );
              channel = session.openChannel("sftp");
              channel.connect();
              try {
                  File f = new File("E:/apache-tomcat-7.0.65/bin/" + this.fileName);
                  sftp.put(new FileInputStream(f), f.getName());
              } catch (Exception e) {
                  e.printStackTrace();
              }
              channel.disconnect();
              sftp.disconnect();
          } catch (JSchException e) {
              e.printStackTrace();
          }
      

      【讨论】:

        最近更新 更多