Programming & Development / April 18, 2025

Spring Batch + SFTP: Export Images from Database and Upload to Remote Server

Spring Batch BLOB SFTP image export file transfer Spring Integration

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:

  1. Reads BLOB images from the database,
  2. Saves them to the local file system,
  3. 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:

  1. 🔍 It reads image data from the database.
  2. 💾 It saves each image to a specified local directory.
  3. 📤 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



Comments

No comments yet

Add a new Comment

NUHMAN.COM

Information Technology website for Programming & Development, Web Design & UX/UI, Startups & Innovation, Gadgets & Consumer Tech, Cloud Computing & Enterprise Tech, Cybersecurity, Artificial Intelligence (AI) & Machine Learning (ML), Gaming Technology, Mobile Development, Tech News & Trends, Open Source & Linux, Data Science & Analytics

Categories

Tags

©{" "} Nuhmans.com . All Rights Reserved. Designed by{" "} HTML Codex