Spring Batch — Upload Files to SFTP Server (Complete Guide)
Uploading files to an SFTP server is a very common enterprise batch requirement — daily reports, partner file exchanges, settlement files, and archival data. In this guide, you’ll learn how to implement a production-ready SFTP file upload job using Spring Batch and Spring Integration SFTP.
๐บ Video walkthrough:
If you prefer learning visually, watch the full implementation explained step by step on YouTube:
๐
Spring Batch SFTP File Upload – Complete Tutorial
Why use Tasklet for SFTP uploads?
- SFTP uploads are usually file-oriented, not record-oriented
- Tasklets provide full control over file existence, naming, and transfer logic
- Simpler restart semantics compared to chunk-based processing
- Ideal for single or small batches of files
Maven dependencies
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-batch</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-sftp</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency>
application.properties
spring.application.name=spring-batch-sftp-upload spring.datasource.url=jdbc:oracle:thin:@localhost:1521/XEPDB1 spring.datasource.username=dbadmin spring.datasource.password=dbadmin1 spring.datasource.driver-class-name=oracle.jdbc.OracleDriver spring.batch.job.enabled=false sftp.host=eu-central-1.sftpcloud.io sftp.port=22 sftp.username=your-username sftp.password=your-password sftp.remote-dir=/pub/example/
SFTP configuration
Spring Integration provides DefaultSftpSessionFactory and
SftpRemoteFileTemplate to interact with an SFTP server.
@Configuration
public class SftpConfig {
@Value("${sftp.host}")
private String host;
@Value("${sftp.port}")
private int port;
@Value("${sftp.username}")
private String username;
@Value("${sftp.password}")
private String password;
@Bean
public DefaultSftpSessionFactory defaultSftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory();
factory.setHost(host);
factory.setPort(port);
factory.setUser(username);
factory.setPassword(password);
factory.setAllowUnknownKeys(true);
return factory;
}
@Bean
public SftpRemoteFileTemplate sftpRemoteFileTemplate() {
return new SftpRemoteFileTemplate(defaultSftpSessionFactory());
}
}
Spring Batch Job configuration
This job uses a single tasklet-based step that uploads a file to the SFTP server.
@Configuration
public class SpringBatchConfig {
@Bean
public Step sftpUploadStep(JobRepository jobRepository,
PlatformTransactionManager transactionManager,
SftpUploadTasklet tasklet) {
return new StepBuilder("sftpUploadStep", jobRepository)
.tasklet(tasklet, transactionManager)
.build();
}
@Bean
public Job dailyFileJob(JobRepository jobRepository,
Step sftpUploadStep) {
return new JobBuilder("dailyFileJob", jobRepository)
.start(sftpUploadStep)
.build();
}
}
SFTP Upload Tasklet
The tasklet validates file existence, ensures the remote directory exists, and uploads the file using an SFTP session.
@Component
public class SftpUploadTasklet implements Tasklet {
@Autowired
private SftpRemoteFileTemplate sftpRemoteFileTemplate;
@Override
public RepeatStatus execute(StepContribution contribution,
ChunkContext chunkContext) throws Exception {
File file = new File("F:/youtube-videos/LikeSubscribe.jpg");
if (!file.exists()) {
throw new RuntimeException("File does not exist");
}
sftpRemoteFileTemplate.execute(session -> {
String remoteDir = "/pub/example";
if (!session.exists(remoteDir)) {
session.mkdir(remoteDir);
}
try (InputStream is = new FileInputStream(file)) {
session.write(is, remoteDir + "/" + file.getName());
}
return null;
});
return RepeatStatus.FINISHED;
}
}
REST API to trigger job
@RestController
@RequestMapping("/api/batch")
public class JobController {
private final JobLauncher jobLauncher;
private final Job dailyFileJob;
public JobController(JobLauncher jobLauncher, Job dailyFileJob) {
this.jobLauncher = jobLauncher;
this.dailyFileJob = dailyFileJob;
}
@GetMapping("/trigger-sftp")
public ResponseEntity<String> triggerSftpJob() {
try {
JobParameters params = new JobParametersBuilder()
.addLong("startAt", System.currentTimeMillis())
.toJobParameters();
jobLauncher.run(dailyFileJob, params);
return ResponseEntity.ok("SFTP Upload Job triggered successfully.");
} catch (Exception e) {
return ResponseEntity.internalServerError()
.body("Job failed: " + e.getMessage());
}
}
}
Transactional behavior & restartability
- If the tasklet fails, the step is marked as FAILED
- Restarting the job re-executes the upload logic
- Ensure idempotency to avoid duplicate uploads
Production best practices
- Use temporary filenames and rename after upload
- Enable retries for transient network failures
- Prefer key-based authentication over passwords
- Log upload metadata (file name, size, timestamp)
- Validate file checksum after upload if required
FAQ
- Why not use ItemWriter? Tasklets are simpler for file transfers.
- Can I upload multiple files? Yes — iterate over a directory inside the tasklet.
- Is SftpRemoteFileTemplate thread-safe? Yes, when used per execution.
Conclusion
Using Spring Batch with Spring Integration SFTP provides a clean and reliable way to upload files to external systems. Tasklet-based jobs are simple, flexible, and production-friendly for file transfer use cases.
๐ฅ Don’t forget to watch the full YouTube walkthrough:
Spring Batch SFTP File Upload – Step-by-Step Video Guide
๐งฑ Spring Batch Core Components
Understand how ItemReader, ItemProcessor, and ItemWriter work together when exporting data to CSV files.
๐ Spring Batch ItemProcessor Example
Apply transformation and formatting logic before writing records into CSV output files.
๐ CSV to Database with Spring Batch
Compare inbound (CSV → DB) and outbound (DB → CSV) batch processing patterns.
๐ซ Skip Policy & Error Handling
Handle write failures and formatting errors gracefully while exporting large datasets.
๐ Conditional Flow in Spring Batch Jobs
Control job execution paths based on CSV generation success or failure.
๐งต Multithreaded Step in Spring Batch
Improve export performance by parallelizing data processing and CSV writing steps.