Upload Arquivos

Local Storage

Salvando os arquivos em Disco

Local Storage Upload

Vamos criar dois pacotes para separarmos: o service e o controller. O pacote de service ficará nossa camada de serviço com a nossa regra de negócio, onde realizaremos a ação de salvar o arquivo e o pacote de controller vai ser usado para realizarmos nossas requisições HTTP.

@Service
public class UploadFileService {

    public File salvarLocalmente(MultipartFile webFile) throws Exception{
        Path caminhoDaPasta = Paths.get("C:\\imagem");
        Files.createDirectories(caminhoDaPasta);
        Path novoCaminhoDoArquivo = caminhoDaPasta.resolve(webFile.getOriginalFilename());
        Files.copy(webFile.getInputStream(), novoCaminhoDoArquivo, StandardCopyOption.REPLACE_EXISTING);
        return novoCaminhoDoArquivo.toFile();
    }

}

Vamos aprofundar mais nesses métodos.

Começaremos pelo método salvarLocalmente da classe UploadFileService:

  1. A classe MultipartFile faz parte do Spring Framework e representa um arquivo carregado em uma solicitação multipart que geralmente é usada para uploads de arquivos via HTTP.
  2. Com a utilização da classe Path realizamos a definição do caminho da pasta de destino especificando onde o arquivo será salvo no disco local.
  3. Caso o diretório passado anteriormente não exista, o método createDirectories da classe Files garantirá a criação do diretório.
  4. Próximo passo é realizar a cópia do arquivo enviado para o novo local indicado no novo caminho e indica que qualquer arquivo existente com o mesmo nome deve ser substituído.
  5. Por fim retornamos o objeto Path para um objeto File.

No método salvarLocalmente da classe UploadFileController:

  1. A anotação @RestController marca a classe como um controlador Spring especializado para Web RESTful. Já a @RequestMapping define a URL base para todos os endpoints dessa classe. O @Autowired injeta automaticamente uma instância do UploadFileService na classe UploadFileController para permitir que o controlador use os métodos definidos no serviço.
  2. Definimos o endpoint com @PostMapping e o consumes = {MediaType.MULTIPART_FORM_DATA_VALUE} indica que este endpoint aceita dados de formulário multipart, o que é necessário para upload de arquivos.
  3. A classe MultipartFile aparece novamente na assinatura do método justamente para indicar que será preenchido com o arquivo enviado na solicitação. E usamos a classe ResponseEntity para retornar uma mensagem de resposta do tipo String.
  4. No bloco try iremos chamar o método salvarLocalmente do serviço e retorna um objeto File que representa o arquivo salvo.
ℹ️ Informação
O multipart é um tipo de conteúdo que permite a transmissão de diferentes tipos de dados em uma única mensagem HTTP.

Swagger Upload

Antes de avançarmos um pouco mais, precisamos adicionar nas dependências a interface gráfica e a API do Swagger:

        <!-- Interface Gráfica -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
            <version>2.3.0</version>
        </dependency>

        <!-- API do Swagger -->
        <dependency>
            <groupId>org.springdoc</groupId>
            <artifactId>springdoc-openapi-ui</artifactId>
            <version>1.7.0</version>
        </dependency>

Após isso, vamos acessar o endereço http://localhost:8080/swagger-ui/index.html para acessarmos o endpoint criado.

Veja que o nosso endpoint de salvar localmente já está disponível para utilizarmos.

Conforme realizamos no desenvolvimento, é solicitado o arquivo para salvarmos localmente. Após escolher o arquivo é só executar:

Deu tudo certo com o nosso envio do arquivo. O código 200 significa sucesso e além disso a confirmação através da mensagem de retorno que adicionamos.

Só pra tirar a prova, vamos dar uma olhadinha no disco local? E aí está o arquivo, no caso a imagem salva.

Postman Upload

Com o Postman instalado vamos criar uma nova requisição. Como vamos adicionar um arquivo, nesse caso vai ser do tipo POST.

  1. Adicionamos o endpoint para o envio do arquivo.
  2. Selecionaremos a opção Body e do tipo form-data. (Lembra do consumes = {MediaType.MULTIPART_FORM_DATA_VALUE}?)
  3. A chave será file, o Tipo File e ao clicar no campo Value aparecerá a opção para adicionar o arquivo da máquina local.

Depois de adicionarmos o arquivo é só enviar a requisição:

Assim como vimos anteriormente no Swagger, recebemos a mensagem de retorno informando que deu tudo certo com nosso upload e também o código 200.

Acessando o arquivo

Agora que já fizemos o upload do arquivo, chegou a hora de acessarmos do disco. Nisso, vamos adicionar mais um método no controller. Como vamos buscar o arquivo, a nossa requisição será do tipo GET:

  1. Utilizamos novamente a classe ResponseEntity mas dessa vez retornando o tipo byte que será o conteúdo do arquivo de imagem. O parâmetro produces = MediaType.IMAGE_JPEG_VALUE indica que o método retorna um conteúdo do tipo image/jpeg.
  2. Definimos o caminho da imagem que queremos acessar a através do filePath. Será usado a classe Files novamente para ler todos os bytes do arquivo que queremos acessar e armazena no array de bytes imagem.
  3. Por última cria um ResponseEntity com status HTTP 200 OK e define o tipo de conteúdo da resposta como imagem do tipo JPEG e define o corpo da resposta com o array de bytes da imagem lido do arquivo.
ℹ️ Informação
Para fins didáticos usamos alguns caminhos e nome de arquivos de forma estática. Mas em aplicações reais utilizadas nas empresas e/ou outros projetos de maior escala esse caminho é sinalizado de forma dinâmica e passado geralmente pela equipe de arquitetura.

Usando o Swagger

Agora no Swagger apareceu mais um endpoint para testarmos:

Ao clicar em executar, mostrará a imagem que adicionamos anteriormente e que passamos o endereço para acessá-la:

Usando o Postman

Adicionamos o nosso endereço com o endpoint ver arquivo, a requisição será do tipo GET e depois enviamos a requisição:

Tudo certo em acessarmos o arquivo localmente:

Agora que já sabemos fazer o upload de arquivos localmente, vamos nos desafiar um pouco mais. Dessa vez, iremos realizar o upload utilizando a nuvem, nesse primeiro momento usando a AWS.