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

最近在项目开发中要使用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), 默认端口号是22
			session = 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", "ip.*", 22,
					"xxx", 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:/ccc/cccc/ccc/Download	*/
		String path = "F:/ccc/cc1/ccc/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:/aaaa/bbb/ccc/Download

4、path路径格式不对,比如path=/D/APPS/apps_srv/LOCALAPP/TFRM/test//ccc/Download

解决方法:请使用正确的系统路径,比如path=F:/ccc/ccc/ccc/Download
 

展开阅读全文

没有更多推荐了,返回首页