在项目中遇到了这个问题 转自 https://blog.csdn.net/qq_34721505/article/details/78262673
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", "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