解决JSch连接SFTP的三大常见错误

发布时间:2026/6/27 5:55:43
解决JSch连接SFTP的三大常见错误 使用sftp服务时用到jsch类去实现远程连接ssh服务这次在实现的过程中遇到了这样几类错误记录一下供参考问题1Algorithm negotiation fail原因由于我现在用的jsch版本和服务器版本不兼容导致客户端算法无法匹配服务器如何确认在用jsch连接之前设定输出日志查看客户端和服务器支持的解密算法区别如何修正升级版本到2.28.2并在pom.xml中显示的指定版本问题2verify:false原因和第一个问题一样版本不兼容但是我解决完版本问题之后发现还是报这个错误历史版本是jsch0.1.54版本后来升级到0.1.55仍然报错最终升级到2.28.2依然报错后来在pom.xml里显式的排除了老版本的jsch才彻底解决这个问题主要原因是版本冲突了如何确认在生成的jar中查看 jar 包内 META-INF/MANIFEST.MF解压jsch-0.1.55.jar打开META-INF/MANIFEST.MF里面会有Implementation-Version: 0.1.55这个是 maven 打包真实版本虽然我声明了2.28.2版本但是打包的内容仍然是0.1.55.如何修正1.显式声明版本在项目pom.xml中直接依赖jsch:2.28.2利用最短路径优先规则覆盖如果项目含有多个模块相互依赖则每个都加上依赖2.使用exclusions排除冲突版本dependencydependency groupIdcom.github.mwiede/groupId artifactIdjsch/artifactId version2.28.2/version exclusions exclusion groupIdcom.jcraft/groupId artifactIdjsch/artifactId /exclusion /exclusions /dependency问题3SSH_FX_NO_SUCH_FILE出现这个错误已经表示连接没有问题看字面意思就是服务器不存在要上传的目标路径因为sftp不会自动建立目录所以需要手动递归建立各级目录最终使用jsch正确连接并上传文档的代码如下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; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.util.Properties; public class SftpUtil { private final String host; private final int port; private final String username; private final String password; private Session session; private ChannelSftp channelSftp; public SftpUtil(String host, int port, String username, String password) { this.host host; this.port port; this.username username; this.password password; } /** * 对外方法1建立SFTP连接 * 用setPassword */ SuppressWarnings(deprecation) public void sftpConnect() throws JSchException { if (session ! null session.isConnected()) { return; } JSch jsch new JSch(); session jsch.getSession(username, host, port); // 直接使用废弃方法加注解消除警告 session.setPassword(password); Properties config new Properties(); // 依靠该配置绕过主机指纹校验替代setHostKeyVerifier config.put(StrictHostKeyChecking, no); session.setConfig(config); // 连接超时30秒 session.connect(30000); // 打开SFTP通道 ChannelSftp channel (ChannelSftp) session.openChannel(sftp); channel.connect(); this.channelSftp channel; } /** * 对外方法2上传文件自动创建远程多级目录 * param localFilePath 本地文件绝对路径 * param remoteFullPath 远程完整路径 /xxx/yyy/file.txt */ public void sftpUpload(String localFilePath, String remoteFullPath) throws Exception { // 先确保连接已初始化 sftpConnect(); File localFile new File(localFilePath); if (!localFile.exists() || !localFile.isFile()) { throw new Exception(本地文件不存在 localFilePath); } // 截取远程父目录 int lastSlashIndex remoteFullPath.lastIndexOf(/); String remoteParentDir remoteFullPath.substring(0, lastSlashIndex); // 递归创建目录解决 SSH_FX_NO_SUCH_FILE mkdirRecursive(remoteParentDir); // 上传文件 try (InputStream inputStream new FileInputStream(localFile)) { channelSftp.put(inputStream, remoteFullPath); } } /** * 内部递归创建远程多级目录等价 mkdir -p */ private void mkdirRecursive(String remoteDir) throws SftpException { if (remoteDir null || remoteDir.isBlank()) { return; } String[] dirArr remoteDir.replaceFirst(^/, ).split(/); String currentPath /; for (String dir : dirArr) { if (dir.isBlank()) { continue; } currentPath dir /; try { channelSftp.cd(currentPath); } catch (SftpException e) { if (e.id ChannelSftp.SSH_FX_NO_SUCH_FILE) { channelSftp.mkdir(currentPath); channelSftp.cd(currentPath); } else { throw e; } } } } /** * 关闭连接释放资源 */ public void close() { if (channelSftp ! null channelSftp.isConnected()) { channelSftp.disconnect(); } if (session ! null session.isConnected()) { session.disconnect(); } } // 测试入口 public static void main(String[] args) { SftpUtil sftp new SftpUtil(你的ip, 端口, 你的用户名, 你的密码); try { sftp.sftpConnect(); System.out.println(SFTP连接成功); sftp.sftpUpload(D:/test.txt, /data/upload/202606/test.txt); System.out.println(文件上传完成); } catch (Exception e) { e.printStackTrace(); } finally { sftp.close(); } } }