You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 18:15:32