¿Cómo puedo acceder a archivos de imagen en MongoDB y enviarlos al cliente usando Express.js?

Aug 18 2020

Guardé algunos archivos de imagen en MongoDB usando mongoose. Las imágenes se envían desde un formulario HTML y luego se envían a MongoDB a través de una solicitud Express POST. Luego, quiero acceder a esos archivos de imagen en MongoDB a través de una solicitud GET y luego enviarlos al lado del cliente. El código para esto se ve así:

app.get("/showallimages", (req, res) => {

    Image.find({}).exec((error, records) => { // Image is the database schema model. 

        var img1 = Buffer.from(records[0].img.data, "base64"); // First image coming from MongoDB.
        var img2 = Buffer.from(records[1].img.data, "base64"); // Second image coming from MongoDB.
        var images = [img1, img2];

        res.writeHead(200, {
            "Content-Type": "image/png",
        })

        var i = 0;
        for (i; i <= images.length; i++) {
            res.end(images[i]); // I am expecting this to send both images to the client side, but instead I am only getting the first image to be displayed. 
        }

    })

})

Si consigo "imágenes" de console.log, obtengo los datos binarios de ambos archivos:

console.log(images); 

  <Buffer ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 64 00 64 00 00 ff ec 00 11 44 75 63 
6b 79 00 01 00 04 00 00 00 22 00 00 ff ee 00 0e 41 64 6f 62 65 00 64 ... 8728 more bytes>,
  <Buffer 89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52 00 00 05 39 00 00 03 84 08 06 00 
00 00 6a f3 35 f1 00 00 00 01 73 52 47 42 00 ae ce 1c e9 00 00 00 f2 ... 397757 more bytes>

Espero que esto envíe ambas imágenes al lado del cliente, pero en cambio solo obtengo la primera imagen que se mostrará.

Se agradece cualquier explicación sobre cómo puedo enviar más de un archivo en este proceso. También avíseme si estoy eligiendo la forma correcta de lograrlo.

¡Gracias!

Respuestas

1 Victor_Maciel Aug 20 2020 at 19:16

Tu código tiene un error lógico. cuando se llama a res.end (), express finaliza el proceso de respuesta en la primera imagen, su ciclo no llega a la siguiente iteración. Además, no puede tener varias respuestas para una solicitud. Pero puede enviar la matriz Buffer con representación JSON usando res.json(images).

En el cliente , para mostrar las imágenes recibidas como búferes desde el servidor: debe convertirlas al formato original haciendo esto:

// server response
const images = response.map(buffer => {
  const rawBuffer = buffer.toString("base64");
  const imageSrc = "data:image/png;base64," + rawBuffer;
  const image = document.createElemment("img");
  image.src = imageSrc;
  return image;
})

/* 
In this method you can control how you will show the images in the client 
(to test, just append to any div)
*/

O, si solo desea mostrar las imágenes sin ninguna manipulación, intente esto:

app.get("/showallimages", (req, res) => {

    Image.find({}).exec((error, records) => { // Image is the database schema model. 

        var img1 = Buffer.from(records[0].img.data, "base64"); // First image coming from MongoDB.
        var img2 = Buffer.from(records[1].img.data, "base64"); // Second image coming from MongoDB.
        var images = [img1, img2];

        const formatedImages = images.map(buffer => {
          return `<img src="data:image/png;base64,${buffer.toString("base64")}"/>`
        }).join("")
        
        res.send(formatedImages)

    })

})