Need to export images stored in your database as BLOBs and upload them to an SFTP server? 🖼️📤 This guide will walk you through building a Spring Batch job that:
- Reads BLOB images from the database,
- Saves them to the local file system,
- Uploads them to an SFTP server — all in one flow.
🔌 Step 1: Add Required Dependencies
Update your pom.xml
with the following:
xml
<dependencies>
<!-- Spring Batch -->
<dependency>
<groupId>org.springframework.batch</groupId>
<artifactId>spring-batch-core</artifactId>
</dependency>
<!-- Spring Integration for SFTP -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-sftp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-core</artifactId>
</dependency>
<!-- Optional: Java DSL support -->
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-java-dsl</artifactId>
</dependency>
<!-- Database Driver -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
🌐 Step 2: SFTP Configuration
Create the connection config to your SFTP server.
java
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
@Configuration
public class SftpConfig {
@Bean
public DefaultSftpSessionFactory sftpSessionFactory() {
DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
factory.setHost("sftp.example.com");
factory.setPort(22);
factory.setUser("your-username");
factory.setPassword("your-password");
factory.setAllowUnknownKeys(true); // Avoid in production
return factory;
}
}
📦 Step 3: Configure the SFTP Upload Channel
Set up a message handler that will send files over SFTP.
java
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.sftp.outbound.SftpMessageHandler;
import org.springframework.messaging.MessageHandler;
@Configuration
public class SftpIntegrationConfig {
@Bean
@ServiceActivator(inputChannel = "sftpChannel")
public MessageHandler sftpMessageHandler(SessionFactory<LsEntry> sftpSessionFactory) {
SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory);
handler.setRemoteDirectoryExpressionString("'/remote/images/'");
return handler;
}
}
✍️ Step 4: Enhanced ItemWriter – Local Save + SFTP Upload
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.file.FileHeaders;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.support.MessageBuilder;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
@Component
public class ImageFileWriter implements ItemWriter<ImageEntity> {
private static final String OUTPUT_DIR = "/path/to/local/folder/";
@Autowired
private MessageChannel sftpChannel;
@Override
public void write(List<? extends ImageEntity> items) throws Exception {
for (ImageEntity item : items) {
File file = saveImageLocally(item);
sendToSftp(file);
}
}
private File saveImageLocally(ImageEntity image) throws IOException {
File file = new File(OUTPUT_DIR + image.getFilename());
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(image.getImageData());
}
return file;
}
private void sendToSftp(File file) {
sftpChannel.send(MessageBuilder.withPayload(file)
.setHeader(FileHeaders.FILENAME, file.getName())
.build());
}
}
⚙️ Step 5: Batch Configuration with SFTP Integration
Make sure the batch job uses the new writer.
java
import org.springframework.batch.core.*;
import org.springframework.batch.core.configuration.annotation.*;
import org.springframework.batch.item.*;
import org.springframework.batch.item.data.RepositoryItemReader;
import org.springframework.context.annotation.*;
import org.springframework.data.domain.Sort;
import java.util.Collections;
@Configuration
@EnableBatchProcessing
public class ImageBatchConfig {
@Bean
public RepositoryItemReader<ImageEntity> reader(ImageRepository repo) {
RepositoryItemReader<ImageEntity> reader = new RepositoryItemReader<>();
reader.setRepository(repo);
reader.setMethodName("findAll");
reader.setSort(Collections.singletonMap("id", Sort.Direction.ASC));
return reader;
}
@Bean
public ItemProcessor<ImageEntity, ImageEntity> processor() {
return image -> image; // Optional transformation
}
@Bean
public Step imageStep(StepBuilderFactory stepBuilderFactory,
ItemReader<ImageEntity> reader,
ItemProcessor<ImageEntity, ImageEntity> processor,
ImageFileWriter writer) {
return stepBuilderFactory.get("imageExportStep")
.<ImageEntity, ImageEntity>chunk(10)
.reader(reader)
.processor(processor)
.writer(writer)
.build();
}
@Bean
public Job imageExportJob(JobBuilderFactory jobBuilderFactory, Step imageStep) {
return jobBuilderFactory.get("imageExportJob")
.start(imageStep)
.build();
}
}
✅ What This Setup Does
When you run your Spring Batch job:
- 🔍 It reads image data from the database.
- 💾 It saves each image to a specified local directory.
- 📤 It sends each saved image to your SFTP server.
🧠 Pro Tips
- Security: Avoid
allowUnknownKeys = true
in production. Instead, use trusted host keys. - Performance: You can batch upload or parallelize the SFTP uploads if needed.
- Testing: Tools like FileZilla Server or SFTPGo are great for local testing.
📌 Summary
Combining Spring Batch and Spring Integration for SFTP gives you a powerful way to handle ETL-style file transfers. You’ve now got a complete workflow to:
✅ Read images from your DB
✅ Save them locally
✅ Ship them off to an SFTP server
Let me know if you'd like to add:
- Thumbnail creation
- FTP fallback
- Email notification on completion
- File compression before upload