I'm trying to make a simple website where I can upload an image to MongoDB and return it. All was going well until I got to the returning the image portion.
Right now, I can upload an image to the website using multer, when I upload the image do the database, it gets converted into binary data. Could anyone please show me how I would be able to convert the binary data to an image? that'll greatly appreciated!!
Schema & Model
const mongoose = require('mongoose');
const fileStorageOneSchema = mongoose.Schema({
img: {
data: Buffer,
contentType: String
}
})
const fileStorageOne = mongoose.model("fileStorageOne", fileStorageOneSchema);
module.exports = fileStorageOne
Multer Storage
const fileStorageOne = multer.diskStorage({
destination: './uploads/fileOne/',
filename: (req,file,cb)=> {
cb(null, file.fieldname + ' - ' + Date.now() + path.extname(file.originalname))
}
})
Express Upload to MongoDB
app.post('/upload_filestorageone', (req,res)=> {
uploadFileStorageOne(req, res, (err)=> {
if(err) {
console.log(err);
res.redirect('/')
} else {
const newImage = new fileStorageOneModel({
img: {
data: fs.readFileSync(path.join(__dirname + '/uploads/fileOne/' + req.file.filename)),
contentType: 'image/png'
}
})
newImage.save((err)=> {
if(err) {
console.log(err);
res.redirect('/')
} else {
console.log('Successfully uploaded a photo!');
res.redirect('/filestorageone')
}
})
}
})
})
Express Return the Image
app.get('/filestorageone/:id', (req,res)=> {
fileStorageOneModel.findOne({}, (err,data)=> {
if(err) {
console.log(err)
} else {
const image = new Buffer(data.img.data).toString('base64')
return res.json(image)
}
})
})
EJS Upload
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
</head>
<body>
<header>
<%- include('./partials/header') %>
</header>
<%- include('./partials/version') %>
<div class="submit-image-style">
<form action="upload_filestorageone" method="POST" enctype="multipart/form-data">
<input type="file" name="fileStorageOneImages">
<button type="submit">Submit</button>
</form>
</div>
<div class="output-style">
<% image.forEach((image)=> { %>
<a href="/filestorageone/<%= image._id %>"><%= image._id %></a>
<% }) %>
</div>
</body>
</html>
Sorry for the messy code, still pretty new to it!
Instead of sending the image with the .json()
method, you'll want to set the appropriate content type so that the browser knows that it's an image, then just .send()
the buffer:
app.get("/filestorageone/:id", (req, res) => {
fileStorageOneModel.findOne({}, (err, data) => {
if (err) {
console.log(err);
} else {
return res.type(data.img.contentType).send(data.img.data);
}
});
});
Here I'm using .type()
which can also look up the correct mime type from a file extension, but you could just as well use .header('Content-Type', data.img.contentType)
.
I've also left out the new Buffer()
call since it's already a Buffer
.
As a side-note, assuming you're using multer
and DiskStorage
, you don't need to construct the path with path.join()
and req.file.filename
, as the full path can be found from req.file.path
. You can also use req.file.mimetype
so that you get the correct content type for also non-PNG images.