DEV Community

Hernani Almeida
Hernani Almeida

Posted on

Armazenando imagens protocolo SFTP com java - Springboot

Ferramentas necessárias:

Neste post vamos abordar o armazenamento de imagens utilizando o protocolo SFTP, vamos subir um servidor SFTP utilizando a chave SSH Importante mecanismo de autenticação que asseguram a proteção de dados e informações dentro de um container docker e enviar imagens para este servidor através de uma api rest java.
Crie uma aplicação Springboot, como nosso objetivo e apenas demonstrar o envio de imagens via SFTP não vamos nos preocupar com padrões arquiteturais.
Crie uma pasta na raiz do projeto com o nome de sua escolha e dentro desta pasta um arquivo dockerfile e cole dentro dele os seguintes comandos.
dockerfile

FROM ubuntu:latest

RUN mkdir -p /var/run/sshd

RUN apt update && \
    apt install -y openjdk-8-jdk && \
    apt install -y openssh-server

RUN useradd -rm -d /home/remote_user -s /bin/bash remote_user && \
    echo remote_user:password1234 | chpasswd

RUN mkdir /home/remote_user/.ssh && \
    chmod 700 /home/remote_user/.ssh

COPY id_rsa.pub /home/remote_user/.ssh/authorized_keys

RUN chown remote_user:remote_user -R /home/remote_user/.ssh && \
    chmod 600 /home/remote_user/.ssh/authorized_keys

CMD [ "/usr/sbin/sshd" , "-D"]
Enter fullscreen mode Exit fullscreen mode

E um arquivo com o nome docker-compose.yml com a seguinte configuração no mesmo
docker-compose.yml

version: '3.7'
services:
  app:
    container_name: sftp
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - '58898:22'
Enter fullscreen mode Exit fullscreen mode

Feito isso, via cmd, entre na pasta onde esta localizado os arquivos dockerfile e docker-compose.yml e rode o seguinte comando para criar uma chave de segurança SSH
ssh-keygen -t rsa -m PEM -f id_rsa apos rodar o comando sera pedido para você escrever uma frase e depois confirmar esta frase para gerar o ssh.
ssh
Ainda dentro desta pasta via cmd rode o comando docker compose up -d e será criado nosso servidor dentro de um container docker.
Image description
Já podemos acessar nosso servidor através do Filezila CLient
*Obs: Password tem que ser o mesmo especificado no dockerfile, neste caso password1234
Image description

Vamos utilizar a lib JSch para armazenar a imagem recebida no servidor SFTP, para isto adicione a seguinte dependência em seu projeto.

<!-- https://mavenlibs.com/maven/dependency/org.lucee/jsch -->
<dependency>
    <groupId>org.lucee</groupId>
    <artifactId>jsch</artifactId>
    <version>0.1.55</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Crie uma classe de configuração do JSch para acessar nosso servidor junto com os métodos necessarios.
SftpConfig

package com.example.sftp;

import com.jcraft.jsch.*;

import java.io.InputStream;


public class SftpConfig {

    /* criar canal para acessar servidor sftp */
    public static ChannelSftp setupJsch() throws JSchException {

        Session jschSession = null;

        Channel sftp = null;

        JSch jsch = new JSch();
        JSch.setConfig("StrictHostKeyChecking", "no");
        //jsch.setKnownHosts("/home/remote_user/.ssh/known_hosts");
        jschSession = jsch.getSession("remote_user", "localhost", 58898);

        // authenticate using private key
        // jsch.addIdentity(<destino da chave ssh>);

        // authenticate using password
        jschSession.setPassword("password1234");

        // 10 seconds session timeout
        jschSession.connect(100000);

        sftp = jschSession.openChannel("sftp");

        return  (ChannelSftp) sftp;

    }

    /* armazenar imagem servidor SFTP */
    public static void salvarImagemSftp(InputStream storedImage, String originalFilename) throws SftpException, JSchException {

        Session jschSession = null;

        Channel sftp = null;
        // transfer file from local to remote server
        ChannelSftp channelSftp = setupJsch();
        channelSftp.connect(50000);

        channelSftp.put(storedImage,channelSftp.getHome() + "/" + originalFilename );

        channelSftp.exit();

        System.out.println("Done");

    }

    /* buscar imagem servidor sftp e transferir para pasta local */
    public static void buscarImagemSftp(String originalFilename) throws SftpException, JSchException {

        Session jschSession = null;

        Channel sftp = null;
        // transfer file from local to remote server
        ChannelSftp channelSftp = setupJsch();
        channelSftp.connect(50000);

        channelSftp.get(channelSftp.getHome() + "/" + originalFilename, "C:\\Users\\Dell\\Desktop\\testeImagem" );

        channelSftp.exit();

        System.out.println("Done");

    }

    /* deletar imagem servidor sftp */
    public static void deletarImagemSftp(String nomeImagem) throws SftpException, JSchException {

        Session jschSession = null;

        Channel sftp = null;
        // transfer file from local to remote server
        ChannelSftp channelSftp = setupJsch();
        channelSftp.connect(50000);

        channelSftp.rm(channelSftp.getHome() + "/" + nomeImagem);

        channelSftp.exit();

        System.out.println("Done");

    }
}
Enter fullscreen mode Exit fullscreen mode

Agora vamos criar uma classe controller para testarmos o envio de imagens para nosso servidor SFTP e uma classe model para mapear a imagem que vamos receber pelo input via controller.
Imagem

import org.springframework.web.multipart.MultipartFile;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Imagem {

    private MultipartFile file;
}
Enter fullscreen mode Exit fullscreen mode

ImagemController

package com.example.sftp;

import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.io.InputStream;

@RestController
public class ImagemController {

    @PostMapping("/imagem")
    public void armazenarImagemApenasSftp(Imagem imagem) throws IOException {
        InputStream image = imagem.getFile().getInputStream();

        try{
            SftpConfig.salvarImagemSftp(image, imagem.getFile().getOriginalFilename() );
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new IOException("Erro ao salvar imagem no cdn");
        }
    }

    @GetMapping("/imagem")
    public void buscarImagemSftp() throws IOException {

        try{
            SftpConfig.buscarImagemSftp("tcc.png");
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new IOException("Erro ao salvar imagem no cdn");
        }
    }

    @DeleteMapping("/imagem")
    public void deletarImagemSftp() throws IOException {

        try{
            SftpConfig.deletarImagemSftp("tcc.png");
        }catch (Exception e){
            System.out.println(e.getMessage());
            throw new IOException("Erro ao salvar imagem no cdn");
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

Vamos testar nossa aplicação via postman.

requisicao para salvar imagem

Image description

imagem salva em nosso servidor

Image description

requisicao para buscar imagem servidor SFTP e tranferir pasta local

Image description

imagem salva na pasta passada como path

Image description

requisicao para deletar imagem servidor SFTP

Image description

imagem deletada do servidor SFTP

Image description

E isso ai devs mas um conhecimento passado, deixarei no meu github para quem quiser acessar o projeto
Deixo aqui também meu linkedin para quem quiser me adicionar, grato a todos que leram este artigo e bora aprender galera.

Discussion (0)