Solucionado (ver solução)
Solucionado
(ver solução)
6
respostas

[DUVIDA] salvando arquivos no banco

Bom dia tenho uma API feita em REST com Spring boot, nessa api tenho uma modelo de class de Produto com seus atributos, o cliente me falou para atribuir mais um tipo de atributo para salvar fotos do produto, como seria a melhor forma de fazer isso? Lembrando que tenho tambem um aplicativo android para acessar a API e buscar os produtos salvos, sendo assim tenho que mostrar a imagem salva no sistema web e no aplicativo, pensando dessa maneira, e bom salvar a foto no banco, ou o caminho da foto? Estou confuso, alguem com um bom conhecimento que ja possou por isso, poderia me dar um rumo? Obrigado

6 respostas
solução!

Oi Michel, tudo bem?

Dá para fazer das duas formas: gravar a imagem no banco de dados ou armazenar o arquivo em um local e gravar apenas a URL no banco, tem alguma restrição de negócio envolvida? Nos sistemas atuais é comum utilizarmos por exemplo, um serviço como o AWS S3 para armazenar esse tipo de arquivo: https://aws.amazon.com/s3/

Temos um curso desse recurso aqui na alura: https://www.alura.com.br/curso-online-aws-s3-manipule-e-armazene-na-nuvem

Se quiser gravar no banco dá também, por exemplo:

File image = new File(path);
FileInputStream fis = new FileInputStream ( image );

String sql="insert into imgtst (username,image) values (?, ?)";
pst=con.prepareStatement(sql);

pst.setString(1, user);
pst.setBinaryStream (2, fis, (int) file.length() );

Mas recomendo fortemente que tente utilizar a opção 1, haha.

Abraço!

Oi otavio. Esse serviço implemento no sistema ele? Vou fazer esse curso e ver se consigo fazer oque pretendo, você acha que fazendo esse curso da pra ter conhecimento no que te falei? eu consegui salvar a imagem no banco, mais li varios artigos dizendo que não e bom, até mesma por performance né :(. Então irei fazer o curso, fazendo o curso vc acha que consigo salvar essa imagem e retornar para o cliente ver no front end? e até msm nos aplicativos? tenho aplicativo android e IOS, sera que tambem eles conseguem acessa? muito obrigado e vou começar o curso agora

Otavio uma outra coisa, na pratica, como seria o primeiro procedimento? (ou armazenar o arquivo em um local e gravar apenas a URL no banco).

Poderia me dar um norte novamente kk

Otavio boa tarde, poderia verificar, fiz o codigo que criar um arquivo temporario na sua maquina, depois passei esse arquivo temporario para um permanente, salvando a foto com o cogido do produto.

Algo assim.

@PostMapping("/upload") @PreAuthorize("hasAuthority('ROLE_CADASTRAR_PRODUTO')") public void upload(@RequestParam MultipartFile foto) {

    try {
        Path arquivoTemp = Files.createTempFile(null, null);
        Files.copy(foto.getInputStream(), arquivoTemp, StandardCopyOption.REPLACE_EXISTING);
        caminhoFoto = arquivoTemp.toString();
        System.out.println(caminhoFoto);
    } catch (IOException e) {
        throw new RuntimeException("erro ao tentar gerar o arquivo");
    }
}

aqui eu criei um arquivo temporario, e depois fiz o seguinte.

@PostMapping
    @PreAuthorize("hasAuthority('ROLE_CADASTRAR_PRODUTO')")
    public ResponseEntity<Produto> salvar(@RequestBody Produto produto) {
        Produto produroRetornado = produtoRepository.save(produto);
        Path origem = Paths.get(caminhoFoto);
        Path destino = Paths.get("C://Upload/" + produroRetornado.getCodigo() + ".png");

        try {
            Files.copy(origem, destino, StandardCopyOption.REPLACE_EXISTING);
            produroRetornado.setCaminhoFoto(destino.toString());
            Produto produtoAux = produtoRepository.findOne(produroRetornado.getCodigo());
            BeanUtils.copyProperties(produroRetornado, produtoAux, "codigo");
            produtoRepository.save(produtoAux);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return ResponseEntity.status(HttpStatus.CREATED).body(produroRetornado);
    }

Ai agora na minha entidade produto, no banco de dados está o caminho dela com o nome da foto, tipo assim.

C:\Upload\2.png

Está correto assim? é esse caminho que devemos salvar? e outra coisa, eu tive que criar a pasta na mão de upload na raiz da minha maquina, e quando for subir pro servidor, no deploy, como que fica?

Otavio fiz diferente aqui mano, agora criei uma pasta no meu projeto chamada upload, na raiz do meu projeto, agora toda vez que eu mandar a requisação para o path /upload ele ja gera o arquivo dentro dessa pasta, acho que assim fica melhor né? Mais se a aplicação for grande e tiver varias fotos, isso não pode encomodar? Ou é normal, e desculpa o encomodo, é que nunca passei por isso antes, entao to um pouco perdido, segue o codigo pra vc ver.

private static String diretorioUpload = System.getProperty("user.dir")+"/uploads";
@PostMapping("/upload")
@PreAuthorize("hasAuthority('ROLE_CADASTRAR_PRODUTO')")
    public void upload(@RequestParam MultipartFile foto) {
        StringBuilder filesName = new StringBuilder();
        Path fileNameAndPath = Paths.get(diretorioUpload,foto.getOriginalFilename());
        filesName.append(foto.getOriginalFilename());
        try {
            Files.write(fileNameAndPath, foto.getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

Assim que geralmente é feita? e agora eu so salvo o caminho da imagem no banco? Seria essa a primeira opção que vc comentou? Ou to na idéia errada?

Uma outra coisa, no banco eu salvo só o nome? ou tenho que passar o caminho toda dela?

Exemplo: Salvo como examplo o caminho todo? tipo

C:\Users\Alisson\Documents\workspace-sts-3.9.7.RELEASE\solufix\uploads\download.jpg

ou salvo apenas o nome, que seria no caso download, ou salvo apos a pasta do projeto? ficando uploads/download.jpg

Otavio concluido aqui, fiz o curso do aws, muito bom por sinal, e muito pratico e sem contar da segurança. Muito obrigado TMJ