sexta-feira, 2 de setembro de 2016

upload de arquivo para o node via angular e arquivo para o banco via knex em poucos passos

cHJpbWVpcmFtZW50ZSwgZm9yYSB0ZW1lciE=

Olá, hoje vou documentar algo importante, que parece simples, de repente não funciona, e lá na frente você descobriria que era uma bobagem, um detalhe.

Hoje é dia de fazer upload para um servidor nodejs!

Agora vamos aos nossos requisitos básicos:

  1. O node.js rodando bonito e cheiroso na sua linha de comando
  2. Um editor de texto, pode ser o netbeans pra javascript (hehehehe)
  3. Um editor de texto qualquer 
  4. PostgreSQL devidamente instalado e configurado
  5. Tem mais coisas, mas com isso aí em cima o resto pegamos na viagem
Por motivos de faz tempo que não uso, vamos tocar o tutorial num opensuse. Ver como que tá o KDE e coisa e tal...

Pra instalar o nodejs, abra o konsole e:
sudo zypper in nodejs

Para instalar o PostgreSQL, aproveite o konsole e:
sudo zypper in postgresql postgresql-server postgresql-contrib

Agora é a parte em que configuramos esse SGBD. Nesse opensuse (assim como em qualquer outro linux) você pode dar um ps auxf pra ver cadê as coisas. 

Sem surpresas, temos o diretório de dados em /var/lib/pgsql/data. Basta seguir os passos já documentados neste outro artigo aqui e teremos login com senha:

Eu sei que você já fez, mas não esqueça de, após mexer no pg_hba.conf reiniciar o serviço de banco:

sudo service postgresql restart


Por motivos de desejo evitar mais fadiga, vou instalar o pgadmin
 sudo zypper in pgadmin3

Depois de instalado você terá essa graça de interface gráfica:


Pra quem nunca usou antes, o passo agora é conectar-se com o localhost usando o usuário postgres que mexemos a senha pra podermos trabalhar:

Para este exemplo que estamos tocando, crie um banco chamado galeriaapp:


Muita paz.

Agora deixe essa molezinha de lado e vamos criar nosso projeto nodejs+express+knex. Retorne ao konsole e mande a seguinte letra:
mkdir galeriaservice
cd galeriaservice
npm init

Não paremos por aí, vamos começar instalando o básico:
npm install express knex pg --save

Nunca vou me acostumar com a feiura da saída de sucesso do npm. Mas sim, adiante. Seu projeto vai versionar o banco e esse é um trabalho para as migrações do knex. Instale a brincadeira e inicialize seu projeto:

sudo npm -g install knex
knex init .

O knex init gerou um arquivo de perfis de conexão, vamos abrir esse arquivo e mexer umas coisas nele. Não precisaremos de suporte a sqlite, por exemplo, e não teremos um perfil diferente de development neste caso aqui. Posto que estamos de kde, vamos instalar o kate pra editar coisas:
sudo zypper in kate highlighting-kate

Agora ao knexfile.js:
kate knexfile.js

Este arquivo deverá ficar assim:

Agora vamos criar nosso primeiro arquivo de migração. Feche o kate e:
knex migrate:make cria_tabela

Aqui no meu caso ele criou um arquivo chamado "/home/sombriks/galeriaservice/migrations/20160902014534_cria_tabela.js"

Mas o que é isso realmente?

Abra o arquivo no kate pra irmos desvendando o mistério:
kate migrations/20160902014534_cria_tabela.js

Neste arquivo nós vamos definir nossa tabela. será de responsabilidade do knex criar ela pra gente. Mas não só isso: este arquivo de migração também saberá como "descriar" tudo o que ele fez. com isso, sempre seremos capazes de avançar ou recuar nosso modelo de dados.

Como? Muito abstrato? Nada tema, apenas saiba que isso pode ajudar muito no futuro, então vá treinando o uso disso.

Dentro de um arquivo de migração do knex não iremos escrever SQL diretamente. Em vez disso, vamos usar a API do schema builder do knex pra criar a tabela que segue abaixo:

Tanto o up quanto o down devem retornar o builder ou uma promessa. ambos chegaram de brinde ali.
Enquanto o up se ocupa de criar a tabela, o down joga ela fora.

Vamos experimentar nossa migração? Feche o kate e no konsole mande um latest:
knex migrate:latest

Ali discreto, uma única linha de feedback, nem parece que deu certo. Retorne, todavia, ao pgadmin e atualize o banco:


Olha nossa tabela criada e feliz ali.
Caso você queria/precise desfazer as alterações de banco, assim como temos o latest, há também o rollback:
knex migrate:rollback
Ele rodará o down das migrações do último lote executado (no nosso caso só uma migração mesmo).

Há ainda as tabelas knex_migrations e knex_migrations_lock. Elas são tabelas de metainformação, servem só pra sabermos quantas migrações foram executadas e se há alguma migração executando no momento. Estas tabelas não serão motivo de preocupação em 90% do tempo.

Vamos adiante.

Hora de colocarmos o express pra trabalhar.

Quando rodamos o npm init lá no começo, ele nos indagou por um tal de entry point, e tinha um valor padrão lá: index.js. Pois bem, é hora de criarmos esse arquivo:
touch index.js
kate index.js

Aqui definimos os pontos básicos de entrada do serviço de galeria. As rotas são:

RotaPropósito
GET /listlistar as imagens, mas sem os arquivo de imagem
GET /:idimagemrecuperar os bytes da imagem apenas
POST /saveSalva uma nova imagem
DELETE /:idimagemRemove uma imagem

Agora é só fazer as consultas de banco de dados:

Após todas as rotas, dê para o app trabalhar a porta 3000:



E depois disso, hora de rodar! siga para o konsole e digite:
node index.js
Pelo firefox já podemos conferir o serviço em pé, mas não tem muito pra ver ainda:

Vamos agora desenvolver o aplicativo cliente para este serviço. Pelo konsole (pode abrir outro se não quiser derrubar o serviço), vamos criar:
cd ..
mkdir galeriacli
cd galeriacli
npm init
npm install angular --save
npm install browserify --save-dev


Um pouco sobre esses comandos:

  1. Fizemos uma nova pasta e inicializamos o projeto npm nela
  2. Instalamos o angular e salvamos a dependência
  3. Instalamos o browserify e salvamos a dependência de desenvolvimento (isto é, dispensável em produção)
Vamos cuidar de instalar mais coisas, mas tudo a seu tempo.

Crie o index.html:
touch index.html
kate index.html

Neste projeto vamos usar o browserify, então poderemos organizar um pouco melhor os scripts. Não que sejam muitos, mas pro nosso exemplo devem dar.

Teremos o entry point, o index.js:

kate index.js

Como promessa é dívida, crie o serviço e o controle que estamos dando require ali.
kate galservice.js:

kate galctl.js

Note que vamos compilar esses caras no bundle.js, por isso que podemos usar require/export e por isso que eles não foram incluídos no index.html.

Para maior comodidade, instale o browserifi globalmente:
sudo npm -g install browserify

Agora é hora da magia:
browserifiy index.js -o bundle.js
E no index.html já pdemos ver o aplicativo se desenhando:

Temos ainda nosso primeiro problema relacionado a este tipo de arquitetura: Cross-Origin Request. Isso significa que o servidor bloqueia chamadas via xmlhttprequest que não tenham origem nele mesmo. Algo entre frescura e segurança.

A solução é adicionar os cabeçalhos necessários no lado do express/node:

Não esqueça de reiniciar o servidor ao realizar a alteração.

Na realidade, faça o seguinte: instale o nodemon:
sudo npm -g install nodemon
Agora para rodar o serviço você simplesmente chama o nodemon na pasta do serviço:

Temos agora o nosso problema de fazer o upload propriamente dito.
O plugin que eu recomendo é o ng-file-upload. No projeto galeriacli, instale-o e torne-o dependência do angular:
npm install ng-file-upload --save


E você deve "compilar" novamente o index.js. Aliás, vamos fazer diferente:
sudo npm -g install budo
budo index.js --serve bundle.js --live --open


Você pode transformar essa linha de comando em um npm script, mas isso eu deixo com você.
Retorne ao html e adicione o atributo ngf-select="ctl.carrega($file)" ao botão em tela:

E no galctl.js, adicione esta função que acabamos de referenciar:

Seguindo essa montagem de trás pra frente, é hora de definir no serviço (galservice.js) o upload propriamente dito:

E é isso. Toca fazer o upload da primeira imagem. Vai ocorrer o seguinte erro:

Isso ocorre porque o corpo da postagem, que deveria conter os bytes da imagem, está nulo.
Para resolver isso, devemos instalar no lado do serviço, mais especificamente no express, o bodyParser. Na pasta do projeto do serviço:
npm install body-parser --save

e no index.js temos que configurar ele:


É muito importante, ao tipificar o middleware do bodyParser, informar valores razoáveis. O bodyParser.raw(), por exemplo, é bom indicar uma lista bem seleta de content-types que ele recebe e um tamanho máximo de payload que não comprometa seu servidor.

Tente fazer o upload novamente. Algumas imagens começarão a aparecer:


Mas e a lista de imagens? por que não aparece na tela?
Em resumo porque a referência do this do javascript é flutuante. Usando o velho truque do var self = this o problema é sanado.

E agora... É isso.

Temos banco, upload, modularização... Um norte. Dá pra tocar coisa melhor a partir deste código, temos o browserify nas mãos e mal começamos a explorar o que ele pode fazer.

O código deste exercício pode ser conferido aqui e aqui.

No mais, até mais.

Nenhum comentário :

Postar um comentário