I've been beating my head over this and I can't find a proper solution. I want to be able to upload images to the server via socket.io emit and save them to a MongoDB database later. How do I do this? I've seen people doing it with base64 encoding but I can't figure out how that exactly works, there are other questions on this website asking about sending an image to client from server via socket.io but none about this. All help is appreciated. <3
Goal: To upload an image to server with socket.emit('image', someimagefile)
or similar.
I'd really appreciate if you provide a similar way to send an image to the client.
I've been beating my head over this and I can't find a proper solution. I want to be able to upload images to the server via socket.io emit and save them to a MongoDB database later. How do I do this? I've seen people doing it with base64 encoding but I can't figure out how that exactly works, there are other questions on this website asking about sending an image to client from server via socket.io but none about this. All help is appreciated. <3
Goal: To upload an image to server with socket.emit('image', someimagefile)
or similar.
I'd really appreciate if you provide a similar way to send an image to the client.
Share Improve this question edited Dec 25, 2019 at 12:30 MasOOd.KamYab 97413 silver badges27 bronze badges asked Dec 25, 2019 at 12:27 Srivetsuki KurosakiSrivetsuki Kurosaki 711 gold badge1 silver badge3 bronze badges 2- 6 Don't use base64... it's pointless. All you're doing is adding 33% overhead to the size, wasting CPU, memory usage, for zero benefit. Web Sockets and Socket.IO support binary transfer. Additionally, why would you want to send it over socket.IO? A normal HTTP request will work fine. Also, while you can shove that binary data in your MongoDB database, it's rarely the best solution. Better to just store the asset on disk so you can serve it up using normal CDNs and what not later. – Brad Commented Dec 25, 2019 at 19:22
- See also socket io, node js, Simple example to send image/files from server to client – ggorlen Commented Mar 11, 2021 at 20:38
3 Answers
Reset to default 10As you mentioned, you can convert the image to base64
using FileReader.readAsDataURL
and send the encoded string, and decode it on the server:
document.getElementById('file').addEventListener('change', function() {
const reader = new FileReader();
reader.onload = function() {
const base64 = this.result.replace(/.*base64,/, '');
socket.emit('image', base64);
};
reader.readAsDataURL(this.files[0]);
}, false);
socket.on('image', async image => {
const buffer = Buffer.from(image, 'base64');
await fs.writeFile('/tmp/image', buffer).catch(console.error); // fs.promises
});
Or better use FileReader.readAsArrayBuffer
to get an array of bytes that you'll send to the server.
document.getElementById('file').addEventListener('change', function() {
const reader = new FileReader();
reader.onload = function() {
const bytes = new Uint8Array(this.result);
socket.emit('image', bytes);
};
reader.readAsArrayBuffer(this.files[0]);
}, false);
socket.on('image', async image => {
// image is an array of bytes
const buffer = Buffer.from(image);
await fs.writeFile('/tmp/image', buffer).catch(console.error); // fs.promises
});
To receive from the server:
// Server side
socket.emit('image', image.toString('base64')); // image should be a buffer
// Client side
socket.on('image', image => {
// create image with
const img = new Image();
// change image type to whatever you use, or detect it in the backend
// and send it if you support multiple extensions
img.src = `data:image/jpg;base64,${image}`;
// Insert it into the DOM
});
Base64 can work, but one more thing to keep in mind is that socket buffer size limit is 1 MB. (This can be increased according to docs).
So I guess if the file size is huge, its better to stream it with something like socket.io-stream
i don't know if any one is looking for it anymore but I made possible to send media via socket.io... here is the code:
// sending media from client side
$("#send_media").change(function (e) {
var data = e.originalEvent.target.files[0];
var reader = new FileReader();
reader.onload = function (evt) {
var msg = {};
msg.file = evt.target.result;
msg.fileName = data.name;
socket.emit("base64 file", msg);
console.log(msg)
};
reader.readAsDataURL(data);
});
// showing media to ui
socket.on("base64 image", (msg) => {
console.log("as", msg);
$(".messages")
.append(`<img src=${msg.file} alt="Red dot" />`);
scrollToBottom();
});
// sending media from server side
socket.on("base64 file", function (msg) {
console.log("received base64 file from server: " + msg.fileName);
socket.username = msg.username;
io.to(roomId).emit('base64 image', //exclude sender
// io.sockets.emit(
// "base64 file", //include sender
{
file: msg.file,
fileName: msg.fileName,
}
);
});