Hola amigos ya llevamos varios tutoriales hablando sobre sails Js para autenticar ususarios con redis y tokens, registro de usuarios y actualizar datos del perfil.
para esto vamos a seguir trabajando en el mismo repositorio https://github.com/herel/api-login
1.- ¿Cómo crear variables de entorno?
Como vimos en los tutoriales anterirores configuramos nuestro archivo .env que contiene las variables de entorno para poder ejecutar una nueva api sin tener que mover mucho codigo debemos agregar a nuestras variables accessKeyId, secretAccessKey y Bucket. yo las agregue con los siguientes nombres:
MAIN_DB_ADAPTER="sails-mongo" MAIN_DB_HOST="localhost" MAIN_DB_PORT="27017" MAIN_DB_DB="********" TOKEN_KEY="********" REDIS_PORT=6379 REDIS_HOST="localhost" REDIS_DB=1 DOMAIN_APP="http://herelodin.com" DOMAIN_API="http://api.herelodin.com/v1.0/" MAIN_S3_KEY="**********DZ3LY2A" MAIN_S3_KEY_SECRET="*************vZLQ5hr0*******" MAIN_S3_BUCKET="*******"
deberan configurar AMAZON S3 con sus respectivas llaves.
2.- ¿Cómo crear un route en SailsJs?
Como vimos en otros tutoriales decidimos deshabilitar blueprints,actions entre otros, por lo que tenemos que crear la url (end point) donde vamos a subir la imagen en BASE64 para esto vamos al archivo config/routes.js y agregamos el siguiente codigo
module.exports.routes = { '/': { view: 'pages/homepage' }, 'POST /v1.0/account' : 'AccountController.create', 'POST /v1.0/account/login' : 'AccountController.login', 'PUT /v1.0/account' : 'UserController.update', 'POST /v1.0/media' : 'MediaController.upload' };
Como podemos observar creamos la url de tipo POST llamada /v1.0/media donde ejecutaremos la funcion upload del archivo MediaController vamos.
3.- ¿Cómo crear un servicio en sails?
Ya tenemos configuradas las variables de entorno y el end point que recibe la imagen ahora debemos crear un servicio que se encargara de recibir la imagen en base64 convertirla a un archivo y subirla en amazon s3.
Debemos crear el archivo api/services/UploadService.js con el siguiente codigo:
var aws = require('aws-sdk'); aws.config.update({ accessKeyId : process.env.MAIN_S3_KEY, secretAccessKey : process.env.MAIN_S3_KEY_SECRET }); var s3 = new aws.S3(); module.exports = { base64 : function(base64,fileName){ return new Promise(function (resolve, reject){ var decodedImage = new Buffer(base64.replace('data:image/png;base64,',''), 'base64'); s3.upload({ Bucket: process.env.MAIN_S3_BUCKET, Key: fileName, Body: decodedImage }, function (err, data) { if(err) return reject(err); return resolve(data); }); }); } }
en este pequeño codigo inicializamos amazon que previamente instalamos con el comando:
sudo npm install aws-sdk --save
agregamos el accessKeyId y secretAccessKey y creamos un objeto nuevo con la configuracion de amazon s3 lista para subir archivos.
tambien creamos una función llamada base64 que recibe dos parametros el string con la imagen y el nombre del archivo, creamos un promise para notificarle cuando se termine de subir el archivo o ocurra un error y convertimos el string en un archivo blob de tipo imagen con la función new Buffer
4.- ¿Cómo crear un controller en sailsJs?
hasta este punto ya tenemos:
- end point donde recibimos la imagen en base64
- servicio que se encarga de subir la imagen a amazon s3
No hace falta el controller que indicamos en el archivo routes.js para esto creamos un controller en api/controllers/MediaController con la función upload.js
var moment = require('moment'); module.exports = { upload : function(req,res){ var params = req.allParams(); var date = moment().format('DD-MM-YYY-hh-mm-ss'); if(!params.image) return res.send(412, { error : true, message : "image is required", status : 412 }); async.waterfall([ function upload(cb){ UploadService.base64(params.image,`${date}.png`) .then(function($result){ return cb(null,$result); }).catch(cb) } ], function done(err,result){ if (err && err.status) return res.send(err.status, err); else if (err) return res.send(500, { error: true, message: "Internal server error", status: 500 }); return res.json(result); }); } }
¿Que hace este pequeño codigo?
- importamos moment que vamos a utlizarlo para crear el nombre del archivo con la fecha actual dia-mes-año-hora-minutos-segundos.png
- validamos que viene la imagen en los parametros
- mandamos a llamar el servico y le pasamos el string con la imagen base64 y el nombre temporal
- si todo sale bien respondemos el objeto que mando amazon con la url
- Si algo sale mal mostramos el error correspondiente
5.- Pruebas con postman
vamos a probar el endpoint con postman para esto busquemos una imagen y la convertimos a base64
5.1- validando errores
Si no enviamos la imagen nos debe responder el siguiente error
5.2- subiendo imagen
Si agregamos el atributo image con la data obtenemos el siguiente mensaje
pueden probar el end point aqui http://api.herelodin.com/v1.0/media o descargar el repositorio
¡Genial ! la imagen se subio con exito y amazon s3 nos respondio la url que asigno https://momazos.s3.amazonaws.com/19-05-182018-12-48-22.png pero que podemos hacer con esto.
- Si agregamos un policie podemos saber que usuario hizo el request y actualizar su foto de perfil y en vez de responder la imagen respondemos un objeto con el usuario actualizado y la nueva imagen de perfil
- si tenemos un formulario con varios campos y 1 con uno o varios archivos podemos ir subiendo las imagenes mientras el usuario llena el formulario y al final enviar los datos con las urls de las imagenes.
En nuestro siguiente post vamos a realizar un ejemplo para actualiza la foto de perfil del usuario logueado y en vez de subir base64 subir uno de tipo file.