Conocer y comprender c贸mo se realizan las conexiones hacia los servidores a trav茅s de internet y sus implicaciones en el desarrollo de servidores

1

Bienvenida y presentaci贸n del curso

2

Qu茅 es Node y c贸mo instalarlo

3

驴Qu茅 son y c贸mo se usan las peticiones HTTP?

4

M茅todos, cabeceras y estados

5

Cuerpo y query de la petici贸n

Crear un servidor HTTP en Javascript, y comenzar a escuchar y responder peticiones desde un cliente .

6

Crear un servidor HTTP desde NodeJS

7

驴C贸mo pueden venir las peticiones?

8

Recibir informaci贸n desde el cliente: Body y Query

9

Informaci贸n contextual: Leer las cabeceras

10

Tipos de respuesta: Vac铆a, plana, con datos y estructurada

11

Respuestas coherentes

12

Servir archivos est谩ticos

13

Errores: C贸mo presentarlos e implicaciones en la seguridad

Comprender y desarrollar la arquitectura b谩sica de un backend en NodeJS, y comunicarse entre m贸dulos

14

Conceptualmente: Rutas, controladores y bases de datos

15

Rutas y capa de red: Responsabilidades y l铆mites

16

Controladores: Definiendo la l贸gica de negocio

17

Almacenando la informaci贸n en una base de datos

Utilizar una base de datos para definir, modelar, almacenar y recuperar la informaci贸n de nuestra aplicaci贸n

18

Tipos de Bases de Datos: Relacionales y No Relacionales

19

Crear y Configurar tu Base de Datos con MongoDB

20

MongoDB: Almacenar y leer datos

21

MongoDB: Actualizar datos

22

MongoDB: Consultar datos

23

MongoDB: Eliminar Datos

24

Gestionar conexiones a la base de datos desde la API

Uso de entidades para crear aplicaciones escalables

25

Escalando la arquitectura: M煤ltiples entidades

26

Relacionando nuestras entidades

27

C贸mo recibir ficheros desde NodeJS

28

Guardar el fichero en el servidor

Conocer el protocolo de websockets, e implementar comunicaci贸n cliente/servidor con SocketIO.

29

WebSockets: Qu茅 son, por qu茅 son interesantes y c贸mo usarlos

30

Manejo de Websockets con NodeJS

31

Conectar la API al servidor de WebSockets

Revisi贸n de lo aprendido, y pr贸ximos pasos

32

Revisi贸n y pr贸ximos pasos

33

Tips para escalar nuestro proyecto

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

C贸mo recibir ficheros desde NodeJS

27/33
Recursos

En esta clase utilizaremos multer para subir archivos a trav茅s de nuestros chats.

Aportes 55

Preguntas 22

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Si te perdiste, pero tienes el c贸digo bien.
Borra los mensajes de la base de datos.
Ten creados dos usuarios en la base de datos.
Ahora ve a crear un chat nuevo (POST) y debe ser un body JSON as铆:

{
	"users": [
		"idDelUser1",
		"idDelUser2"
	]
}

Luego, ve a crear un mensaje (POST), a diferencia de la versi贸n anterior, ahora se de le debe agregar el id del chat correspondiente de la creaci贸n que hicimos.

{
	"chat": "idChat",
	"user": "idUser1",
	"message": "mensaje"
}

Ah铆 puedes crear m谩s mensajes.

Luego para hacer el GET de chat, debes poner el ID del User en la URL:
http://localhost:3000/chat/userId

馃槂

Al enviar la imagen se guardaba como binario, yo solucione el problema as铆 , obteniendo la extensi贸n del nombre original archivo

const path = require("path")
const multer = require("multer")

const storage = multer.diskStorage({
    destination : "uploads/",
    filename : function (req, file, cb) {
        cb(null, file.fieldname + "-" + Date.now() + 
        path.extname(file.originalname))
    }
})

const upload = multer({ storage: storage });

Si usan PostMan y les salta error al usar form-data s贸lo tienen que desactivar el Header de content-type

Por favor, no hagan m谩s en ning煤n curso esto de meter c贸digo y explicarlo por arriba. Hasta la clase anterior todo me funcionaba y hoy me pierdo el d铆a entero tratando de encontrar el error!

Guarda la imagen c贸mo binario, para solucionarlo obtengo la extensi贸n del archivo a cargar.

const multer = require('multer');

const storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'public/uploads/');
    },
    filename: function (req, file, cb) {
        const [name, extension] = file.originalname.split('.');
        cb(null, `${name}-${Date.now()}.${extension}`)
    }
})

const upload = multer({ storage: storage });
router.post('/', upload.single('file'), function (req, res) {
    controller.addMessage(req.body.chat, req.body.user, req.body.message)
        .then((response) => responses.success(req, res, response))
        .catch((error) => responses.error(req, res, error, 400, 'Error en el controlador'))
});

Qu茅 quilombo se me enred贸 todo

El profesor se ve que sabe mucho del tema, lo domina, pero tiene una estrategia pedag贸gica muy deficiente, hay partes del c贸digo que escribi贸 pero nunca salen en el video, uno tiene que estar revisando qu茅 partes diferentes de c贸digo encuentra y adem谩s la clase est谩 muy desordenada, parece que no prepara la clase sino que va escribiendo c贸digo sobre la marcha, se nota por los errores que comete.

creo que es interesante saber que tenemos esta hermosa web: https://www.npmjs.com/
para encontrar lo que necesitemos instalar, como utilizarlo, etc 鈥 Espero sea de provecho este comentario para la comunidad Platzi.

Nota mental: siempre esperar a que finalice la clase y no empezar a desarrollar sin haber finalizado鈥

Hay que darse una vuelta por el c贸digo, porque ha cambiado m谩s cosas de las que explica en el v铆deo, sobre todo en la parte del componente de message.

Comando para el populate del message teniendo en cuenta el chat y los users dentro dechat`.

export const getMessages = async (filterUser: IMessages) => {
  return new Promise((resolve, reject) => {
    MessageModel.find(filterUser)
      .populate('user')
      .populate({
        path: 'chat',
        populate: {
          path: 'users',
        },
      })
      .exec((error, res) => {
        if (error) {
          return reject(error);
        }
        resolve(res);
      });
  });
};

Para los que fueron a ver el archivo y les parecio algo asi鈥
b4f00781b05e514e71c37d4c4268fa39

La solucion es esta o al menos mi solucion

const multer = require('multer');
//esto es nativo a si que no necesitas instalarlo
const path = require('path');

const storage = multer.diskStorage({
  destination:  "uploads/",
  filename: (req, file, cb) => {
    cb(null, file.fieldname + '-' + Date.now() + path.extname(file.originalname))
  }
})

const upload = multer({ storage: storage })

Si te guarda la imagen鈥 pero como un binario sin extensi贸n. Puedes setear el formato de la imagen de la siguiente forma:
(Windows)

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, 'uploads/')
    },
    filename: function (req, file, cb) {
      cb(null, Date.now() + '.jpg') //Appending .jpg
    }
})

const upload = multer({
    storage: storage
})

router.post('/', upload.single('file'), function(req, res){ ...

Cual es el formato json correcto para enviar mensajes ahora?
Porque esto:

{	
	"user": "5dde5d5629714e036671b618",
	"chat": "5dde70a292162a07820c6bf6",
	"message": "Hola Mundo"
}

Me devuelve:

{
  "error": "Informacion inv谩lida",
  "body": ""
}

Muy buena poder ingresar imagenes y documentos desde el multi-part data!!!

Como no podia ver imagenes en mi windows ya que no es tan potente como linux鈥 investige sobre como a帽adir la extencion y poder tener el archivo correto en mi nodejs.

Les comparto una pagina de stackoverflow donde se explica el procedimiento:

https://stackoverflow.com/questions/31592726/how-to-store-a-file-with-file-extension-with-multer

Tiene muchas funcionalidades para poder hacer cositas entretes viendo el repo donde te indican como debe hacerse paso a paso entiendo todo:

https://github.com/expressjs/multer

Se complica el c贸digo y es necesario estar muy atento. Hay que borrar los datos de la base. Ahora para enviar mensaje primero hay que crear al menos 2 usuarios, luego enviarlos como chat y cuando se tenga el id del chat, se puede enviar el mensaje.

Modelo de clases
Para entender mejor el desarrollo presento un peque帽o modelo de clases de los objetos que se utilizan.

Espero que sea de utilidad

Saludos

El proyecto no se puede descargar completo o es mi impresi贸n? deja ir viendo lo que uno necesita y no se puede navegar hac铆a atr谩s

La imagen no deber铆a guardarse en la misma base de datos de mongo?

Bueno para aquellos que seguramente tiene dudas鈥 El profe en ves de filtrar por user, esta filtrando por chat鈥 digamos que cambio la logica esa鈥 Pero como a mi me interesa tambien traer por message por user鈥 cree esto.

network.js

//get message
router.get('/', (req, res) => {
  let filetMessage = {}

  if (req.query.user !== undefined) {
    console.log('soy un user')
    filetMessage = {
      request: req.query.user,
      filter: 'user'
    }
  } else if (req.query.chat !== undefined) {
    console.log('soy un chat')
    console.log(req.query.chat)
    filetMessage = {
      request: req.query.chat,
      filter: 'chat'
    }
  }

  controller.getMessage(filetMessage)
    .then((messageList) => {
      response.success(req, res, messageList, 200)
    })
    .catch((err) => {
      response.error(req, res, 'Unexpected Error', 500, err )
    })
})

controller.js (No hay cambios, si no quieren ponerlo como promesa, es lo mismo)

function getMessage (filetMessage) {
  return new Promise((resolve, reject) => {
    resolve(store.list(filetMessage))
  })
}

store.js

async function getMessage (filterMessage) {
  return new Promise((resolve, reject) => {

      let filter = {} 
      //filetMessage params query ?user=nameUser
      
      if (filterMessage !== {}) {
        if (filterMessage.filter === 'chat') {
          filter = {
            chat: filterMessage.request
          }
        } else if (filterMessage.filter === 'user') {
          filter = {
            user: filterMessage.request
          }
        }
      }
      //se le pasa un parametro para saber que fiktrar
      Model.find(filter)
        .populate('user')
        .exec((err, populated) => {
          if(err) {
            reject(err)
            return false
          }
          resolve(populated)
        })
  })
}

Perd铆 completamente el hilo.

2 d铆as buscando el problema y todav铆a no lo encuentro.

El curso ven铆a de 10 hasta que empez贸 a meter c贸digo sin explicar

Hice el codigo en Typescript con async/await. Todo lo hice en el tag database-populate. Les dejo el link:
https://github.com/Aibique-stage1/telegram-backend-js/tree/database-populate

Hola!! Por favor nos comparten el c贸digo de las clases?

Me podr铆an orientar c贸mo se hace en postman el 鈥淢ultipart Form鈥. ?.
Gracias

cuando hago una peticion get de mi chat me dice que data no esta definido, alguna ayuda?

controller.js

const store = require('./store');

function addChat(users){
    if(!users || !Array.isArray(users)){
        return Promise.reject('Invalid user list')
    }
    const chat={
        users: users,
    };
    return store.add(chat); 
}

function listChats(userId){
    return store.list(userId);
}

module.exports = {
    listChats,
    addChat,
}

model.js

const mongoose = require('mongoose');

const Schema = mongoose.Schema;

const mySchema = new Schema({
    users:{
        type: Schema.ObjectId,
        ref: 'user'
    }

}); 

const model = mongoose.model('Chat', mySchema);

module.exports = model;

network.js

const express = require('express');
const router = express.Router();
const response = require('../../Network/responses');
const controller = require('./controller');

router.post('/', function (req, res){
    controller.addChat(req.body.users)
    .then((data)=>{
        response.success(req, res, data, 201);
    })
    .catch(err=>{
        response.error(req, res, 'Internal error', 500, err)
    })
});

router.get('/:userId', function(req, res){
    controller.listChats(req.params.userId)
    .then(users=>{
        response.success(req, res, users, 200);
    })
    .catch(err=>{
        response.error(req, res, data, 500, err);
    })
})

module.exports = router;

store.js

const Model = require('./model');

function addChat(chat){
    const myChat = new Model(chat);
    return myChat.save();   
}

function listChats(usrId){
    return new Promise((resolve, reject)=>{
        let filter = {};
        if (userId){
            filter = {
                users: userId,
            }
        }
        Model.find(filter)
            .populate('users')
            .exec((err, populated)=>{
                if(err){
                    reject(err);
                    return false;
                }
                resolve(populated);
            })
        
    })
}

module.exports = {
    add: addChat,
    list: listChats,
}

Yo revisando mi codigo mil veces porque segun yo al hacer el post de user me regresaba un array vacio, para una hora despues darme cuenta que nunca hice post y estuve haciendo puros get .-.

Mori ajjajaja tendre q analizar mi codigo muy detalladament por q no entendi como es la cuestion de los enlaces en el chat

debiste escribir el codigo y escribirlo ala par que mal

Les dejo el link con informaci贸n sobre multer

https://www.npmjs.com/package/multer


Me voy de este curso hasta que alguien conteste鈥

Para los que est谩n con la versi贸n de multer 1.4.4

const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, "./uploads");
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname);
  },
});

const upload = multer({ storage: storage });

Ac谩 dejo soluci贸n para que la imagen que suban tenga la extensi贸n y el mismo nombre, para los que estamos cursando este curso en 2021.
La encontr茅 en Medium:
https://medium.com/swlh/how-to-upload-image-using-multer-in-node-js-f3aeffb90657

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
      cb(null, './uploads')
    },
    filename: function (req, file, cb) {
      cb(null, file.originalname)
    }
})
var upload = multer({ storage: storage })```

Si cuando hacen el GET de chats les muestra vac铆o el mensaje, en mi caso es porque deb铆a hacer el return del query en store.js

const getChats = async (userId) => {
    let filter = {};
    if (userId) {
        filter = {
            users: userId,
        }
    }
    try {
        return await Model.find(filter).populate('users').exec();
    } catch (error) {
        throw new Error(error);
    }
}

Por cierto, no estoy usando promesas, estoy trabajando con Async / Await

Les recomiendo apenas termine el video comparar su codigo con el del profesor, ya que en este vide omite algunos pasos y por eso es que al final no siempre funciona algunos detalles del programa

Tuve problema en esta parte cuando lo trabajo desde wls2 en windows 11 (si lo trabajo en el entorno propio de windows 0 problema). El problema es que queda la request de insomia pensando.

Si MongoDB les retorna un error de llave duplicada. Por ejemplo el que a m铆 me devolv铆a鈥

MongoError: E11000 duplicate key error collection: messages_service_nodejs.messages index: user_1 dup key: { user: ObjectId('60b42a2eb3d5f01bc40e32d3') }

Buscando en distintos foros, me d铆 con dos soluciones:

  • Eliminar la colecci贸n donde se encuentra el problema en cuesti贸n ejecutando si se tiene la base de datos en local:
db.collection.drop()

Y en caso de tenerla en Mongo Atlas simplemente se puede hacer en el apartado de collections de forma gr谩fica.
.

  • En m铆 caso, eliminar solo la colecci贸n problem谩tica no me di贸 resultados, y deb铆 eliminar la base de datos por completo, espec铆ficamente lo que hice fue borrar todas las colecciones y no directamente la BD.
    De forma local se hace:
db.dropDatabase()

pd: Debe seleccionarse la base de datos en cuesti贸n antes de ejecutar cualquier comando en la shell de mongo.
.
En Mongo Atlas, borrar las colecciones una por una o directamente toda la base de datos se hace de forma gr谩fica facilmente y no voy a extenderme.
.
Espero les sirva!

No sufras, ve el c贸digo en Archivos y Enlaces, compara con el tuyo y probablemente encuentres lo que te falta por cambiar.

Alguien me puede decir por qu茅 me da error al incluir 鈥渟erver.use(鈥/chat鈥, chat);鈥?

No entiendo por qu茅 me da error s贸lo al incluir esa linea, qui麓zas sea una estupidez, pero no veo el error.

Gracias a todos.

De est谩 manera podemos hacer que Multer guarde la extensi贸n de los archivos. Simplemente agregamos el modulo interno 鈥減ath鈥 de node y agregamos la siguiente configuraci贸n

var multer = require('multer');
var path = require('path')

var storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, Date.now() + path.extname(file.originalname)) //Appending extension
  }
})

var upload = multer({ storage: storage });

Ya correg铆 mi c贸digo y quedo igual al de las clases.
Este es el resultado:
en la parte de insomnia no esta completo porque el numero no me lo genera. 馃槮
Ayuda!!

![](

Mensajes como archivos ayudados con multer. Interesante

termina la parte de integracion de chat e inicia la parte de lectura de ficheros

Est谩n invertidos los videos, creo que este va despu茅s del que le sigue鈥

Aqui tengo una duda, que he estado buscando si quisiera mantener la busqueda en el get de message tanto por el nombre del usuario como por el id del chat como tendria que quedar nuestro controller de getmessages ya intente meterle dos veces el query param para poder filtrar tanto por el chat id y por el name del user y no me sale. 馃槩

woo que bien, hasta aqu铆 vamos al paso!!

por qu茅 mis fotos se guardan como una especie de binario?

Deben tener cuidado cuando env铆en la data como multipart, pues el body llega como: [Object: null prototype].

En todas las clases iba bien hasta que me apareci贸 un error diciendo algo as铆: module mongoose not found
Luego me d铆 cuenta que en verdad Mongoose no exist铆a m谩s en mi proyecto!
Hice checkout en GIT a commits anteriors i Mongoose no apareci贸 en el archivo package.json.
No tengo ni idea qu茅 pudo haber ocurrido. Install茅 de nuevo Mongoose y todo bien.
Pero que raro. Sospecho que fu茅 al instalar Multer.
驴A alguien m谩s le ha ocurrido?

Interesante clase ya sabremos como subir archivos 馃槂

Yo tuve que poner 鈥/:userId?鈥 porque sino me exigia que en la url hubiera un id ^^

Recibir ficheros

Para quienes les sale el error con la base de datos: response error: MissingSchemaError: Schema hasn鈥檛 been registered for model 鈥淯ser鈥.
Use mongoose.model(name, schema).

En el archivo Store.js de la carpeta messaje aparece la siguiente fucion:

<code> 
async function getMessages(filterChat) {
    return new Promise((resolve, reject) => {
        let filter = {};
        if (filterChat !== null) {
            filter = { chat: filterChat };
        }
        Model.find(filter)
            .populate('user')
            .exec((error, populated) => {
                if (error) {
                    reject(error);
                    return false;
                }

                resolve(populated);
            });
    })
}

Para resolver este error debe cambiar la l铆nea: .populate(鈥榰ser鈥). Por la siguiente:

<code> 
.populate('chat')

Ya con esto podr谩n utilizar el request:
localhost:3000/message sin errores habiendo hecho todos los otros cambios de este y los otros tres archivos de la misma carpeta que est谩n publicados.

npm i multer

Al subir la imagen no me la sube como jpg o png, alguien sabe a que se debe eso y como puedo solucionarlo?

Hay el mismo ejemplo, pero con MySQL?