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

如何用Spring Boot高效通过SFTP合并远程大文件(无需本地下载)?

SFTP服务器端文件合并的Spring Boot高效实现方案

要实现无需全量下载文件的SFTP文件合并,核心思路是要么让服务器本地执行合并操作(零网络传输),要么通过流转发仅传输文件片段(不缓存完整文件),以下是两种可行方案:

方案一:通过SSH执行服务器端Shell命令(最优)

直接在SFTP服务器上执行cat命令完成文件合并,全程无需传输文件内容,是效率最高的方式。

实现步骤

  1. 引入依赖:使用JSch库建立SSH连接(Spring SFTP底层也依赖该库)
<dependency>
    <groupId>com.jcraft</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>
  1. 编写合并服务类
import com.jcraft.jsch.*;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.IOException;

@Component
public class SshSftpMergeService {

    public void mergeFilesOnServer(String host, int port, String username, String password,
                                  String sourceA, String sourceB, String targetC) throws JSchException, IOException, InterruptedException {
        JSch jsch = new JSch();
        Session session = jsch.getSession(username, host, port);
        session.setPassword(password);
        
        // 生产环境请替换为合法的主机密钥验证逻辑,不要跳过
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();

        // 打开Shell通道执行合并命令
        Channel channel = session.openChannel("shell");
        // 构造合并命令并退出Shell
        String command = String.format("cat %s %s > %s\nexit\n", sourceA, sourceB, targetC);
        channel.setInputStream(new ByteArrayInputStream(command.getBytes()));
        channel.setOutputStream(System.out); // 可选,用于查看命令执行输出
        channel.connect();

        // 等待命令执行完成
        while (!channel.isClosed()) {
            Thread.sleep(100);
        }
        
        channel.disconnect();
        session.disconnect();
    }
}

注意事项

  • 确保执行命令的SFTP用户对folder_A、folder_B有读权限,对folder_C有写权限
  • 生产环境必须关闭StrictHostKeyChecking=no,配置正确的主机密钥验证或密钥登录方式
  • 如果服务器禁用了Shell通道,该方案不可用,切换到方案二

方案二:基于SFTP流转发(无本地文件缓存)

若无法执行Shell命令,可通过SFTP流直接转发文件内容,全程仅在内存中保留固定大小的缓冲区,不保存完整文件到本地。

实现步骤

  1. 引入依赖:使用Spring官方的SFTP集成模块
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-integration</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-sftp</artifactId>
</dependency>
  1. 配置SFTP连接
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
import org.springframework.integration.sftp.session.SftpRemoteFileTemplate;

@Configuration
public class SftpConfig {

    @Bean
    public DefaultSftpSessionFactory sftpSessionFactory() {
        DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
        factory.setHost("你的SFTP主机地址");
        factory.setPort(22);
        factory.setUser("用户名");
        factory.setPassword("密码");
        
        // 生产环境建议使用密钥登录替代密码
        // factory.setPrivateKey(new File("私钥文件路径"));
        // factory.setPrivateKeyPassphrase("私钥密码");
        
        factory.setAllowUnknownKeys(true); // 生产环境请关闭,配置已知主机
        return factory;
    }

    @Bean
    public SftpRemoteFileTemplate sftpRemoteFileTemplate(DefaultSftpSessionFactory factory) {
        return new SftpRemoteFileTemplate(factory);
    }
}
  1. 编写流合并服务类
import org.springframework.integration.sftp.session.SftpRemoteFileTemplate;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

@Component
public class SftpStreamMergeService {

    private final SftpRemoteFileTemplate sftpTemplate;

    public SftpStreamMergeService(SftpRemoteFileTemplate sftpTemplate) {
        this.sftpTemplate = sftpTemplate;
    }

    public void mergeFilesViaStream(String sourceA, String sourceB, String targetC) {
        sftpTemplate.execute(session -> {
            try (OutputStream targetOut = session.write(targetC, false);
                 InputStream inA = session.read(sourceA);
                 InputStream inB = session.read(sourceB)) {

                byte[] buffer = new byte[8192]; // 8KB缓冲区,可根据网络情况调整
                int bytesRead;

                // 写入A.txt内容
                while ((bytesRead = inA.read(buffer)) != -1) {
                    targetOut.write(buffer, 0, bytesRead);
                }

                // 追加B.txt内容
                while ((bytesRead = inB.read(buffer)) != -1) {
                    targetOut.write(buffer, 0, bytesRead);
                }
                targetOut.flush();
            } catch (IOException e) {
                throw new RuntimeException("文件合并失败", e);
            }
            return null;
        });
    }
}

注意事项

  • 该方案会传输文件内容,但仅占用少量内存缓冲区,适合大文件合并
  • 确保SFTP服务器支持流读写操作(主流服务器如OpenSSH、FileZilla Server均支持)

内容的提问来源于stack exchange,提问作者Chaitanya Pandit

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 14:01:05