Retornando urls de imagens no loopback
Originalmente publicado em 2019-10-11 10:00 no blog Patinete a vela.
A idéia é simples, e bem comum:
Tenho um objeto do tipo Product
que pode ter várias Images
associadas.
O modelo Image
salva o nome do container e o nome do arquivo dessa imagem.
O modelo Product
tem uma relação do tipo hasMany
com o modelo Image
.
Usando o api explorer do loopback, vemos que as imagens retornam apenas
container
e filename
, porém o ideal seria que fossem retornadas urls que
apontassem direto para as imagens e pudessem ser abertas no navegador.
Temos que fazer duas coisas. A primeira é disponibilizar uma api rest para
acessar arquivos armazenados no servidor. A segunda é construir a url toda vez
que alguém quiser acessar um objeto do tipo Image
.
Disponibilizar uma api rest é muito simples. Criamos um datasource do tipo
filesystem
apontando para um diretório local do servidor:
Precisamos também criar um modelo, que chamaremos de container
, que representa
o local onde arquivos são armazenados.
Precisamos também associar o modelo ao datasource:
Com este modelo container
agora está disponível na api explorer do loopback uma
série de métodos que permitem listar containers, imagens dentro de containers,
fazer upload e download de imagens. Esta postagem no blog do
loopback
é muito útil e lista os métodos disponíveis.
Com a configuração acima, na pasta server/storage em nosso servidor poderemos criar pastas (onde cada pasta será um container) e dentro das pastas podemos colocar arquivos. Podemos acessar estes arquivos com a seguinte url:
Por padrão, nosso modelo Image
já tem o nome do container e o nome do arquivo,
então o cliente, ao consumir nossa api, já tem a informação suficiente para
construir a URL para download das imagens.
Mas é muito inconveniente passar para o cliente a responsabilidade de construir a url toda vez que ele precisar acessar uma imagem.
Para evitar isto, vamos criar um operation hook que nos permitirá gerar uma url toda vez que uma imagem for buscada no nosso backend.
Fazemos isto adicionando código ao nosso modelo Image:
Este código adiciona um “observador” à operação loaded
. Esta operação
representa o momento em que um dado já foi buscado no banco de dados e ainda não
foi construído o objeto que será devolvido ao cliente que requisitou tal dado.
Algumas coisas importantes: o arquivo server.js
, que é o principal ponto de
entrada do servidor e é criado automaticamente ao iniciar um projeto loopback,
pode ser importado e ele conterá uma série de informações globais úteis. Se
importarmos na variável app
, encontraremos em app.locals.settings.url
a url do
servidor (por exemplo http://localhost:3000/
caso estejamos executando no
servidor local) e em app.locals.settings.restApiRoot
encontaremos o caminho para
a api rest (por exemplo /api
, caso você esteja usando o padrão).
No código acima nós removemos a barra no final da url e combinamos os diferentes
elementos para gerar a url que aponta para a imagem em função de seu container e
de seu nome de arquivo. Salvamos esta url na variável ctx.data.url
.
Com isto, quando baixamos a lista de imagens obteremos:
O código completo deste exemplo está disponível no GitHub.
Referências
Operation hooks, Loopback Documentation
Storage connector, Loopback Documentation
Managing Objects in LoopBack with the Storage Provider of Your Choice, Strongblog
felipeferri/loopback-images, projeto completo no GitHub.