ChannelSftp.cd(path)时总是抛出com.jcraft.jsch.ChannelSftp.throwStatusError

来源:互联网 发布:lofter(乐乎) 编辑:程序博客网 时间:2024/03/02 14:39

最近在项目开发中要使用sftp上传和下载文件,本人编写了一个测试类,代码如下:

package com.summer.util;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.io.UnsupportedEncodingException;import java.lang.reflect.Field;import java.util.Properties;import org.apache.log4j.Logger;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;/** * 通过SFTP通道实现文件的上传与下载 * API在线文档: * http://epaul.github.io/jsch-documentation/javadoc/com/jcraft/jsch/ChannelSftp.html * @author Administrator *  */public class SFTPUtil {private Logger log = Logger.getLogger(SFTPUtil.class);private static Session session;private static Channel channel;private static ChannelSftp sftp;/** * 创建SFTP通道 *  * @param username *            访问SFTP服务器的用户名 * @param host *            SFTP服务器的IP * @param port *            SFTP服务器的端口号 * @param password *            访问SFTP服务器的密码 * @param timeOut *            访问SFTP服务器超时时间,单位:毫秒 */public ChannelSftp getSFTPConnection(String username, String host,int port, String password, int timeOut) {try {JSch jsch = new JSch();// 参数为sftp服务器的IP、PORT、USERNAME、PASSWORD// getSession(String username, String host, int port), 默认端口号是22session = jsch.getSession(username, host, port);session.setPassword(password);Properties config = new Properties();// Jsch优先使用RSA key type密钥的方式登陆// 此处使用用户名和密码方式登录config.put("StrictHostKeyChecking", "no");session.setConfig(config);// 设置访问超时时间session.connect();log.info("连接会话开启成功!");// 创建sftp通信通道channel = session.openChannel("sftp");channel.connect();log.info("SFTP连接成功");sftp = (ChannelSftp) channel;// sftp.quit();} catch (JSchException e) {log.error("创建sftp通道失败");log.error(e.getMessage());} finally {// sftp通道需返回给调用者,所以fianlly中不能关闭,需在调用后关闭/* * if (sftp != null) sftp.disconnect(); if (channel != null) * channel.disconnect(); if (session != null) session.disconnect(); */}return sftp;}/** * 使用SFTP通道上传文件 *  * @param sftp * @param sourceFile *            要上传的源文件 * @param destFile *            目标文件 * @return 上传成功返回true,失败返回false */public boolean fileUpload(ChannelSftp sftp, String sourceFile,String destFile) {OutputStream outstream = null;InputStream instream = null;try {// 以下代码实现从本地上传一个文件到服务器/usr/uploadFileName.txt文件,如果要实现下载,对换以下流就可以了outstream = sftp.put(destFile);instream = new FileInputStream(new File(sourceFile));byte b[] = new byte[1024];int n;while ((n = instream.read(b)) != -1) {outstream.write(b, 0, n);}outstream.flush();log.info("文件上传成功");return true;// sftp.disconnect();// sftp.quit();} catch (IOException e) {log.error("文件上传失败");log.error(e.getMessage());return false;} catch (SftpException e) {log.error("文件上传失败");log.error(e.getMessage());return false;} finally {try {if (instream != null)instream.close();if (outstream != null)outstream.close();if (sftp != null)sftp.disconnect();} catch (IOException e) {log.error("关闭流失败");log.error(e.getMessage());}}}/** * 断开连接,关闭资源 */public void close() {//closes this channel.if (sftp != null)sftp.disconnect();if (channel != null)channel.disconnect();if (session != null)session.disconnect();}/** * 测试 * @param args * @throws SftpException  * @throws UnsupportedEncodingException  * @throws NoSuchFieldException  * @throws SecurityException  * @throws IllegalAccessException  * @throws IllegalArgumentException  */public static void main(String[] args) throws SftpException, UnsupportedEncodingException, SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {SFTPUtil util = new SFTPUtil();ChannelSftp sftp = util.getSFTPConnection("ftp", "192.168.11.*", 22,"ftp", 30000);Class cl = ChannelSftp.class;  Field field =cl.getDeclaredField("server_version");  field.setAccessible(true);  field.set(sftp, 2); sftp.setFilenameEncoding("GBK");  /*1、文件分隔符使用/,而不要使用\\;2、添加第167-171行代码;3、将路径配置成如下格式:F:/银监会文件交换服务客户端/F049H101331104001/最高人民法院/Download*/String path = "F:/银监会文件交换服务客户端/F049H101331104001/最高人民法院/Download";sftp.cd(path);util.close();}}

Exception in thread "main" 0: Failure

at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2836)
at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2327)
at com.jcraft.jsch.ChannelSftp.cd(ChannelSftp.java:342)

at com.summer.util.SFTPUtil.main(SFTPUtil.java:178)

Failure说明路径错误;Success说明路径正确,但字符集不对;

Exception in thread "main" 0: Success
at com.jcraft.jsch.ChannelSftp.throwStatusError(ChannelSftp.java:2833)
at com.jcraft.jsch.ChannelSftp._realpath(ChannelSftp.java:2327)
at com.jcraft.jsch.ChannelSftp.cd(ChannelSftp.java:342)
at com.summer.util.SFTPUtil.main(SFTPUtil.java:177)

在测试过程中几次遇到如上所示异常信息:出现该异常的原因可能有以下几种情况:

1、ChannelSftp.cd(path)中的路径path不存在,比如写错文件或文件夹的名称等;

解决方法:仔细检查path路径是否正确;

2、ChannelSftp中默认的FilenameEncoding为UTF-8,path所在操作系统的字符集不是UTF-8;

解决方法:添加如下代码

Class cl = ChannelSftp.class;  Field field =cl.getDeclaredField("server_version");  field.setAccessible(true);  field.set(sftp, 2); sftp.setFilenameEncoding("GBK");

"GBK"是path路径所在操作系统字符集,以win7为例,查看操作系统字符集方法如下:

开始-->运行-->cmd,打开DOS命令窗口,右键“标题栏”-->属性-->选项,即可看到操作系统字符集


3、path路径格式不对,比如文件分隔符使用"\\";

解决方法:文件分隔符请使用“/”,例:F:/银监会文件交换服务客户端/F049H101331104001/最高人民法院/Download

4、path路径格式不对,比如path=/D/APPS/apps_srv/LOCALAPP/TFRM/test//最高民人法高/Download

解决方法:请使用正确的系统路径,比如path=F:/银监会文件交换服务客户端/F049H101331104001/最高人民法院/Download

原创粉丝点击