Repositorio con el código solución al desafío 2: Collage de Imágenes del módulo 8 Implementación de API backend Node Express de la beca Desarrollo de aplicaciones Full Stack Javascript Trainee dada por Talento Digital para Chile y dictada por Desafío Latam.
Nuevamente he ido mucho más allá de lo solicitado realizando lo siguiente como adicional:
-Proyecto 100% Responsivo
-Eliminación de Cache de modo de actualizar el front end de manera inmediata ante cambios en el servidor
-Dos maneras de Resetear la data ya sea mediante ruta o mediante intervalo de tiempo
-Creación de vistas 404 (ruta no encontrada) y 413(archivo supera el límite máximo permitido de 5 MB)
- Solución al Desafío - Collage de imágenes
- Tabla de Contenidos
- Requisitos
- Deploy
- Proyecto 100% Responsivo
- Diagrama de Flujo
- Soluciones
- 1. Integrar express-fileupload a Express. (1 Punto)
- 2. Definir que el límite para la carga de imágenes es de 5MB. (2 Puntos)
- 3. Responder con un mensaje indicando que se sobrepasó el límite especificado. (2 Puntos)
- 4. Crear una ruta POST /imagen que reciba y almacene una imagen en una carpeta pública del servidor. Considerar que el formulario envía un payload con una propiedad “position”, que indica la posición del collage donde se deberá mostrar la imagen. (3 Puntos)
- 5. Crear una ruta DELETE /imagen/:nombre que reciba como parámetro el nombre de una imagen y la elimine de la carpeta en donde están siendo alojadas las imágenes. Considerar que esta interacción se ejecuta al hacer click en alguno de los números del collage. (2 Puntos)
- Extra
El proyecto es completamente funcional y esta desplegado en render en el siguiente link
Se ha integrado express-fileupload tal y como muestro a continuación:
import fileUpload from "express-fileupload";
Con la intención de renderizar una vista personalizada he manipulado el tamaño en el siguiente middleware (se muestra una vista personalizada cuando el tamaño del archivo es mayor a 5 MB):
export function crearImagen(req, res) {
const { target_file } = req.files;
const { posicion } = req.body;
if (Object.keys(target_file).length === 0) {
res.status(400).send("Ningun archivo ha sido subido");
return;
}
if (target_file.size > 5 * 1024 * 1024) {
res.status(413).render("pages/413");
return;
}
target_file.mv(
path.resolve("assets", "imagenes", `imagen-${posicion}.jpg`),
(err) => {
if (err) {
console.log("Error77", err);
res.send("Error");
return;
}
console.log("Imagen guardada con exito");
res.render("pages/collage");
}
);
}
Respondo con más que un simple mensaje sino que respondo con una vista personalizada siguiente:
4. Crear una ruta POST /imagen que reciba y almacene una imagen en una carpeta pública del servidor. Considerar que el formulario envía un payload con una propiedad “position”, que indica la posición del collage donde se deberá mostrar la imagen. (3 Puntos)
He creado la siguiente ruta post que cumple con lo solicitado:
router.post("/imagen", crearImagen);
Dicha ruta utiliza la siguiente función crearImagen:
export function crearImagen(req, res) {
const { target_file } = req.files;
const { posicion } = req.body;
if (Object.keys(target_file).length === 0) {
res.status(400).send("Ningun archivo ha sido subido");
return;
}
if (target_file.size > 5 * 1024 * 1024) {
res.status(413).render("pages/413");
return;
}
target_file.mv(
path.resolve("assets", "imagenes", `imagen-${posicion}.jpg`),
(err) => {
if (err) {
console.log("Error77", err);
res.send("Error");
return;
}
console.log("Imagen guardada con exito");
res.render("pages/collage");
}
);
}
5. Crear una ruta DELETE /imagen/:nombre que reciba como parámetro el nombre de una imagen y la elimine de la carpeta en donde están siendo alojadas las imágenes. Considerar que esta interacción se ejecuta al hacer click en alguno de los números del collage. (2 Puntos)
He creado la siguiente ruta delete que cumple con lo solicitado:
export async function deleteImagen(req, res) {
try {
const { nombre } = req.params;
if (nombre) {
console.log("Eliminada con exito ", nombre);
await fs.unlink(path.resolve("assets", "imagenes", nombre));
res
.status(200)
.set("Cache-Control", "no-cache, no-store, must-revalidate")
.send("exito");
}
} catch (error) {
res.status(500).send(error);
}
}
He creado 2 maneras para resetear la data e impedir la persistencia de data no deseada en mi proyecto. El primer método es resetear la data vía una ruta la cual es la siguiente:
router.get("/reset", resetData);
Dicha ruta utiliza la siguiente función:
export async function resetData(req, res) {
const carpeta = path.resolve("assets", "imagenes");
try {
const archivos = await fs.readdir(carpeta);
for (const archivo of archivos) {
const rutaArchivo = path.join(carpeta, archivo);
await fs.unlink(rutaArchivo);
}
console.log("Data reseteada con exito");
res.send("Data reseteada con exito 😄");
} catch (error) {
res.send("Error al resetear la data");
}
}
El segundo método es resetear la data cada 15 minutos vía el intervalo siguiente:
setInterval(async () => {
const carpeta = path.resolve("assets", "imagenes");
try {
const archivos = await fs.readdir(carpeta);
if (archivos.length > 0) {
for (const archivo of archivos) {
const rutaArchivo = path.join(carpeta, archivo);
await fs.unlink(rutaArchivo);
}
console.log("Data reseteada con exito");
}
} catch (error) {
console.log("Error al resetear la data");
}
}, 900000);