如何使用Java将文件从SFTP服务器直接复制至Amazon S3存储桶指定路径
嘿,这个需求我之前在项目里实战过好多次,直接流式传输确实能避免本地磁盘占用,尤其是处理大文件的时候优势特别明显。下面我给你一步步拆解实现方案和代码:
核心思路
核心逻辑其实很简单——直接从SFTP服务器获取文件的输入流,然后把这个流直接传给AWS S3的上传API,全程不需要把文件写到本地磁盘。Java的IO流机制刚好能支持这种“管道式”的传输,既节省空间又提升效率。
所需依赖
你需要引入两个核心库:JSch(用来连接SFTP服务器)和AWS SDK for S3(用来操作S3存储桶)。如果用Maven的话,直接在pom.xml里加这些依赖:
<!-- JSch:SFTP客户端库 --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> </dependency> <!-- AWS S3 SDK v2(推荐用v2,比v1更高效) --> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.20.100</version> </dependency>
完整代码实现
下面是整合好的代码,我加了详细注释,你可以根据自己的配置修改参数:
import com.jcraft.jsch.*; import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import java.io.InputStream; public class SftpToS3Transfer { // -------------------------- 配置参数 -------------------------- private static final String SFTP_HOST = "your-sftp-server.com"; private static final int SFTP_PORT = 22; // 默认SFTP端口是22 private static final String SFTP_USERNAME = "your-sftp-username"; // 可选:用密码或私钥,这里示例用密码,私钥的话需要加载本地密钥文件 private static final String SFTP_PASSWORD = "your-sftp-password"; private static final String S3_BUCKET_NAME = "your-s3-bucket-name"; private static final String S3_REGION = "cn-north-1"; // 替换成你的S3区域,比如us-east-1 // -------------------------- 配置结束 -------------------------- public static void main(String[] args) { // SFTP上的源文件路径 String sftpSourcePath = "/remote/directory/your-file.pdf"; // S3上的目标路径(即对象的Key) String s3TargetKey = "s3-target-folder/your-file.pdf"; try { transferSftpFileToS3(sftpSourcePath, s3TargetKey); System.out.println("🎉 文件从SFTP到S3的传输完成!"); } catch (JSchException | SftpException e) { System.err.println("❌ SFTP操作出错:" + e.getMessage()); e.printStackTrace(); } catch (Exception e) { System.err.println("❌ S3上传出错:" + e.getMessage()); e.printStackTrace(); } } /** * 核心传输方法:从SFTP取流直接上传到S3 */ private static void transferSftpFileToS3(String sftpFilePath, String s3TargetKey) throws JSchException, SftpException { // 1. 建立SFTP连接 JSch jsch = new JSch(); Session sftpSession = jsch.getSession(SFTP_USERNAME, SFTP_HOST, SFTP_PORT); sftpSession.setPassword(SFTP_PASSWORD); // 生产环境注意:不要关闭主机密钥检查!应该将SFTP服务器公钥加入known_hosts sftpSession.setConfig("StrictHostKeyChecking", "no"); sftpSession.connect(); ChannelSftp sftpChannel = (ChannelSftp) sftpSession.openChannel("sftp"); sftpChannel.connect(); // 2. 用try-with-resources自动关闭流和客户端(Java 7+支持) try (InputStream sftpFileStream = sftpChannel.get(sftpFilePath); S3Client s3Client = buildS3Client()) { // 3. 构造S3上传请求 PutObjectRequest uploadRequest = PutObjectRequest.builder() .bucket(S3_BUCKET_NAME) .key(s3TargetKey) // 可选:设置文件的Content-Type,比如"application/pdf" //.contentType("application/octet-stream") .build(); // 4. 直接把SFTP的输入流传给S3,全程不落地本地 s3Client.putObject(uploadRequest, RequestBody.fromInputStream(sftpFileStream, sftpChannel.lstat(sftpFilePath).getSize())); } catch (Exception e) { throw new RuntimeException("传输过程中发生异常", e); } finally { // 手动关闭SFTP资源,确保连接释放 if (sftpChannel != null && sftpChannel.isConnected()) { sftpChannel.disconnect(); } if (sftpSession != null && sftpSession.isConnected()) { sftpSession.disconnect(); } } } /** * 构建S3客户端(用默认凭证链,安全又方便) */ private static S3Client buildS3Client() { return S3Client.builder() .region(software.amazon.awssdk.regions.Region.of(S3_REGION)) // 默认凭证链:会自动从环境变量、IAM角色、~/.aws/credentials等地方取凭证 .credentialsProvider(DefaultCredentialsProvider.create()) .build(); } }
关键注意事项
- SFTP主机密钥安全:生产环境绝对不要设置
StrictHostKeyChecking=no!应该把SFTP服务器的公钥添加到~/.ssh/known_hosts文件中,防止中间人攻击。 - 凭证不要硬编码:代码里的密码、密钥都是示例,生产环境一定要用环境变量、配置中心(比如Spring Cloud Config)或者AWS IAM角色(如果在EC2/EKS上运行,IAM角色是最优解,无需手动管理密钥)。
- 大文件自动分段:AWS SDK v2会自动对大文件(默认超过100MB)进行分段上传,不需要你手动拆分流,底层会处理并发和重试,不用担心内存溢出。
- 资源关闭:一定要用
try-with-resources或者finally块关闭所有流和客户端,避免资源泄漏。 - 异常重试:如果你的网络不稳定,可以添加重试机制,比如用Guava的
Retryer或者AWS SDK自带的重试策略(默认已经有基础重试,但可以自定义)。
内容的提问来源于stack exchange,提问作者sunny rajpal
相关产品推荐
相关产品推荐

