Your current implementation faces an issue as it tries to send multiple images in a single HTTP response, which is not directly supported by HTTP standards. Each HTTP response should be intended for a single resource only. Fortunately, there are several ways to work around this limitation for your specific use case.
Encode Images as Base64
To address this issue, the server can transmit the images back to the client as an array of base64 strings. Here's how:
router.get("/", asyncHandler(async (req, res) => {
const imagesInfo = await Image.find();
const promises = imagesInfo.map((img) =>
sharp(img.data).toFormat('jpeg').toBuffer()
);
Promise.all(promises)
.then((outputBuffers) => {
const base64Images = outputBuffers.map(buffer => buffer.toString('base64'));
res.json(base64Images);
})
.catch((err) => {
console.error('Error:', err);
res.status(500).send('Error.');
});
}));
Below is an example code snippet demonstrating how the client side can handle the encoded image responses:
<div id="container"></div>
<script>
fetch('http://yourserver.com/')
.then(response => response.json())
.then(images => {
const container = document.getElementById('container');
images.forEach(base64Image => {
const img = document.createElement('img');
img.src = 'data:image/jpeg;base64,' + base64Image;
container.appendChild(img);
});
})
.catch(error => console.error('Error:', error));
</script>
However, it's important to note that encoding images as base64 will increase data size by approximately 33%, potentially impacting performance if speed is crucial for your project.
Send Image URLs Instead
Alternatively, you can choose to share the image URLs with the client instead. This method typically serves the same purpose depending on the client's objectives. Since each image likely has a unique file name, you could follow this approach:
router.get("/", asyncHandler(async (req, res) => {
const imagesInfo = await Image.find();
const imageUrls = imagesInfo.map((img) => `http://yourserver.com/images/${img.filename}`);
res.json(imageUrls);
}));
// Endpoint to serve an individual image
router.get("/images/:filename", asyncHandler(async (req, res) => {
try {
const filename = req.params.filename;
const imageInfo = await Image.findOne({ filename: filename });
if (imageInfo) {
const buffer = imageInfo.data;
const image = await sharp(buffer).toFormat('jpeg').toBuffer();
res.contentType('image/jpeg');
res.send(image);
} else {
res.status(404).send('Image not found.');
}
} catch (err) {
console.error('Error:', err);
res.status(500).send('Error.');
}
}));
Keep in mind that if you require raw image data for any reason, this method might not suit your needs out of the box, as you would have to retrieve the raw data individually from each URL returned in the initial request.