使用JSch上传文件至SFTP后丢失扩展名问题求助
SFTP上传文件无扩展名且文件名与目录名相同的问题
问题现象
- 本地.jpg、.txt文件已成功上传至SFTP目录,但上传后的文件无扩展名,且文件名与目标目录名(/SFTPRoot)完全一致
- 手动为SFTPRoot目录下的文件添加扩展名后,文件可正常识别显示
- 尝试使用
File和FileInputStream方式上传时,提示“No Such File”,因此改用当前代码实现
当前实现代码
private final SFTPConfig sftpConfig; private final String KNOWN_HOST = "/Users/xxx/.ssh/known_hosts"; private final String LOCAL_PATH = "C:/Users/xxx/Downloads/"; public void setupJsch(int configType, String fileName) throws JSchException, SftpException { log.info("+++++ CONNECTING TO SFTP +++++"); JSch jsch = new JSch(); jsch.setKnownHosts(KNOWN_HOST); Session jschSession = jsch.getSession(sftpConfig.username(), sftpConfig.remoteHost(), 22); jschSession.setPassword(sftpConfig.password()); jschSession.setConfig("StrictHostKeyChecking", "no"); jschSession.connect(); Channel channel = jschSession.openChannel("sftp"); ChannelSftp sftpChannel = (ChannelSftp) channel; sftpChannel.connect(60000); log.info("+++++ ESTABLISHED CONNECTION +++++"); try { if (configType == 1) { log.info("+++++ BEGIN SENDING {} TO SFTP", fileName); sendFile(sftpChannel, fileName); } else { log.info("+++++ BEGIN DOWNLOADING {} FROM SFTP", fileName); downloadFile(sftpChannel, fileName); } } catch (SftpException | FileNotFoundException e) { log.error("Error downloading/sending the file: {}", e.getMessage()); } sftpChannel.disconnect(); jschSession.disconnect(); log.info("+++++ DISCONNECTED TO SFTP +++++"); } public void sendFile(ChannelSftp sftpChannel, String fileName) throws SftpException, FileNotFoundException { sftpChannel.put(LOCAL_PATH + fileName, sftpConfig.sftpPath()); } public void downloadFile(ChannelSftp sftpChannel, String fileName) throws SftpException, FileNotFoundException { sftpChannel.get(sftpConfig.sftpPath()+"/"+filename,LOCAL_PATH); }
SFTP配置
#---- SFTP CONFIGURATIONS sftp.remote-host=localhost sftp.username=root sftp.password=root sftp.path=/SFTPRoot
尝试过的流上传代码(报错“No Such File”)
//File file = new File(LOCAL_PATH + fileName); //log.warn("File {}: Exist? {} : {}, Path = {} ", file.getName(), file.exists(), file.isFile(), file.getPath()); //sftpChannel.put(new FileInputStream(file), sftpConfig.sftpPath());
问题分析与解决方案
1. 上传文件无扩展名的核心原因
你调用sftpChannel.put时,第二个参数只传了SFTP的目录路径(/SFTPRoot),没有指定远程文件名。JSch的put方法在这种场景下,会默认将远程文件名设置为目录名(即SFTPRoot),直接丢失了原文件的扩展名。
2. 修复上传代码
修改sendFile方法,在远程目录后拼接原文件名,保留扩展名:
public void sendFile(ChannelSftp sftpChannel, String fileName) throws SftpException, FileNotFoundException { // 拼接远程目录与原文件名,确保远程文件和本地文件名一致 String remoteFilePath = sftpConfig.sftpPath() + "/" + fileName; sftpChannel.put(LOCAL_PATH + fileName, remoteFilePath); }
3. 解决流上传方式的“No Such File”问题
流上传报错的大概率原因:
- 本地文件路径拼接错误,或文件实际不存在
- 检查
LOCAL_PATH末尾是否有斜杠,确保和fileName拼接后是有效路径 - 取消注释流上传代码中的日志打印,确认
file.exists()是否为true,排查文件是否真实存在
修正后的流上传代码示例:
public void sendFile(ChannelSftp sftpChannel, String fileName) throws SftpException, FileNotFoundException { File file = new File(LOCAL_PATH + fileName); log.warn("File {}: Exist? {} : {}, Path = {} ", file.getName(), file.exists(), file.isFile(), file.getPath()); if (!file.exists() || !file.isFile()) { throw new FileNotFoundException("本地文件不存在或不是有效文件:" + file.getPath()); } // 指定远程文件名,避免丢失扩展名 String remoteFilePath = sftpConfig.sftpPath() + "/" + fileName; sftpChannel.put(new FileInputStream(file), remoteFilePath); }
4. 额外修复点
下载方法存在拼写错误:filename应为fileName(大小写不一致),会导致编译错误,修正如下:
public void downloadFile(ChannelSftp sftpChannel, String fileName) throws SftpException, FileNotFoundException { sftpChannel.get(sftpConfig.sftpPath()+"/"+fileName, LOCAL_PATH + fileName); }
建议使用File.separator代替硬编码斜杠,适配不同操作系统的路径格式
内容的提问来源于stack exchange,提问作者Eve
相关产品推荐
相关产品推荐

