使用JSch上传文件至SFTP服务器后目标目录无可见文件问题咨询
JSch SFTP上传文件无报错但找不到文件的排查修复方案
问题复现代码
String localFile = "/usr/local/test.pdf"; String remotePath = "/tmp/test.pdf"; JSch jsch = new JSch(); jsch.setKnownHosts("/home/wasadm/.ssh/known_hosts"); jschSession = jsch.getSession(USERNAME, REMOTE_HOST, REMOTE_PORT); jschSession.setPassword(PASSWORD); jschSession.connect(SESSION_TIMEOUT); Channel sftp = jschSession.openChannel("sftp"); sftp.connect(CHANNEL_TIMEOUT); ChannelSftp channelSftp = (ChannelSftp) sftp; channelSftp.put(localFile, remotePath);
核心原因及修复方案
- SFTP chroot目录隔离
多数企业级SFTP服务端会对登陆用户配置chroot隔离,你代码中写的绝对路径/tmp/test.pdf,实际对应服务器物理路径为{ChrootDirectory配置的根目录}/tmp/test.pdf,而非系统根目录下的/tmp路径。
排查方法:连接成功后执行以下代码打印目录信息确认映射关系:
// 打印当前用户工作目录 System.out.println("当前工作目录:" + channelSftp.pwd()); // 打印当前用户根目录下的所有文件 System.out.println("根目录文件列表:" + channelSftp.ls("/"));- 缓冲区未刷入,资源未正常关闭
你当前代码执行put操作后未主动关闭通道和会话,小文件会滞留在传输缓冲区,连接断开时未完成实际磁盘写入。在put逻辑后补充以下代码即可:
channelSftp.exit(); sftp.disconnect(); jschSession.disconnect();- 远程路径冲突
如果远程已存在名为/tmp/test.pdf的目录,JSch默认会把本地文件上传到该目录下,最终路径为/tmp/test.pdf/test.pdf,导致你在预期目录找不到目标文件。
修复方法:上传前先校验路径类型:
try { SftpATTRS attrs = channelSftp.lstat(remotePath); if (attrs.isDir()) { // 存在同名目录,拼接正确的文件路径 String fileName = localFile.substring(localFile.lastIndexOf("/") + 1); remotePath = remotePath + "/" + fileName; } } catch (SftpException e) { // 路径不存在,无需调整 if (e.id != ChannelSftp.SSH_FX_NO_SUCH_FILE) { throw e; } }- 权限校验缺失
部分SFTP服务端会静默返回写入成功,但实际因用户无目标路径写入权限未完成落盘,可在上传后主动校验文件是否存在:
try { channelSftp.lstat(remotePath); System.out.println("文件上传成功,路径:" + remotePath); } catch (SftpException e) { System.out.println("文件上传失败,无对应路径:" + remotePath); }- SFTP chroot目录隔离
辅助排查手段
如果以上方案都未解决问题,可以开启JSch调试日志查看完整传输链路:
JSch.setLogger(new com.jcraft.jsch.Logger() { @Override public boolean isEnabled(int level) { return true; } @Override public void log(int level, String message) { System.out.println("[JSch调试日志] " + message); } });
内容的提问来源于stack exchange,提问作者Madhu Nali
相关产品推荐
相关产品推荐

