Not too long ago I wrote about uploading files to a Node.js server that was making use of the Multer middleware. In that scenario the files were saved to the file system and even though I didn’t demonstrate it, in theory the file metadata would be stored in a database. What if you wanted to store the files in a database as a base64 string instead of on the file system?
We’re going to take a look at what it would take to allow file uploads in Node.js and convert them into base64 strings for database storage.
Let me start by saying that although this is possible, it is best to store your files on the filesystem and not within the database. Storage on the filesystem is cheaper than database storage.
We’re going to start by creating a fresh Node.js project using NPM. Create a project directory somewhere and from your Command Prompt (Windows) or Terminal (Mac and Linux), execute the following:
touch app.js
npm init -y
For simplicity, our entire app will exist in the app.js file. The command npm init -y
will create our package.json file which will house all of the project dependencies.
Now we need to install such dependencies. Execute the following from your Command Prompt or Terminal:
npm install express body-parser multer --save
With everything ready to go we can start coding. Add the following to the project’s app.js file:
var express = require("express");
var bodyParser = require("body-parser");
var multer = require("multer");
var fs = require("fs");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.post("/upload", multer({dest: "./uploads/"}).array("uploads", 12), function(req, res) {
res.send(req.files);
});
var server = app.listen(3000, function() {
console.log("Listening on port %s...", server.address().port);
});
This code was pretty much taken exactly from my previous post on file uploads with Multer and Angular. However notice the following line:
var fs = require("fs");
We’re including this dependency because we need to be able to read the file from the file system. The goal here is to accept the file upload, save it to the file system temporarily, read it to convert into base64, then do cleanup on the file system.
Take a look at the following snippet of code:
app.post("/upload", multer({dest: "./uploads/"}).array("uploads", 12), function(req, res) {
var fileInfo = [];
for(var i = 0; i < req.files.length; i++) {
fileInfo.push({
"originalName": req.files[i].originalName,
"size": req.files[i].size,
"b64": new Buffer(fs.readFileSync(req.files[i].path)).toString("base64")
});
fs.unlink(req.files[i].path);
}
res.send(fileInfo);
});
This snippet will replace the /upload
endpoint in our app.js file. The first thing we do is loop through the array of files that were provided.
We’re going to push our own modified file data to a new array that will eventually be returned.
The file data that we want to keep is the original file name, file size, and then the base64 string representing the file itself. To get the base64 string we read the file synchronously from the file system, add it to a buffer and then convert it to a string. You certainly could use an asynchronous method for reading from the file system, but I chose the synchronous method for simplicity.
After we push to our array we can delete the file from the file system. We don’t need to do this in a synchronous fashion so instead of holding up our execution we just unlink
the files asynchronously.
We saw how to upload files to a Node.js server that uses the Multer middleware. Previously we only cared about leaving the file on the filesystem, but this time around we converted it to a base64 string. This might be useful if you would rather everything be contained in your database. It might also be useful if you have a mobile application with sync.
Keep in mind, I’d actually recommend leaving the files on your file system. File system storage is cheap, its quick, and in my opinion better.