NodeJS image upload to mongodb GridFS with multer
NodeJS image upload to Mongodb with multer.
signup.html
: contains html form for registering with any username and password.login.html
is the landing page. Gallery is private. User has to log in with their username and passwordgallery.html
app.js
handles user authentication with md5
password encryption, as well as creating the storage engine and running the express app.multipart/form-data
from the html body.// create storage engine
const storage = new GridFsStorage({
url: process.env.GALLERYDBURI,
options: {useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true},
file: function(req, file){
const match = [“image/png”, “image/jpeg”];
if(match.indexOf(file.mimetype) === -1){
return {
filename: “file“ + Date.now() + path.extname(file.originalname),
bucketname: “uploads”
};
}
}
});
// initialize GridFS stream and upload up to 5 images
const upload = multer({storage: storage}).array(“files”, 5);
const uploadFilesEngine = util.promisify(upload);
- With the storage engine, you can now control the image uploads and export it to `app.js`. Remember to ask the user to upload at least one file. Or you write the function to accept only one file. In this case, the function accepts at least one file, and a maximum of 5 files. The `array()` functions sets the maximum number of images that can be uploaded. The first parameter is the name of the file `input` tag, in this case, `files`. The second parameter is the maximum number of images. If there's too many files, the `catch()` statement checks for that and alerts the user when they try to upload more than 5 images.
// handle image uploads
async function uploadImages(request, respond){
try {
await uploadFilesEngine(request, respond);
console.log(request.files);
if(request.files.length <= 0)
return respond.send("Ay, select a file! At least ONE file!");
else
respond.send("Good work, now go grab yourself a biscuit or something");
} catch (err) {
console.log(err);
if (err.code === "LIMIT_UNEXPECTED_FILE")
return respond.send("Woah, calm down! How many fingers you got?");
else
return respond.send("Might I interest you in upload error? No? Ok.");
}
}
module.exports = {
uploadFiles: uploadImages
};
- Create the express app server: Require the necessary dependencies; initialize middleware; add the landing, signup and uploads `get` and `post` methods. To use the uploading function from `engines.js`, start by importing it:
> `const engines = require("./engines");`
- This would allow you to call the methods from `engines.js`. The post route, for example, uses the uploading function from engines. So:
> `app.post("/upload", engines.uploadFiles);`
- If you did everything right, you could load the html document from your browser. Side note, the best part about this is that I just found a new way to initialize the connect to the MongoDb server _and_ solved that incessant 'Deprecation warning: blah blah add {newUnifiedTopology: true}' bug!
#### start user database server
- First initialize user database and configure the User Database model.
async function connectUserdb(){
try {
await mongoose.connect(userdbURI, {useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true});
console.log(“connected to userdb!”);
} catch (err) {
console.log(err);
throw(err);
}
}
// configure user model
const userSchema = mongoose.Schema({
username: String,
password: String
});
const User = new mongoose.model(“User”, userSchema);
// initialize mongo userdb server
connectUserdb();
- In `app.js` encrypt the password from the html document with md5 in the signup `post` route's callback function.
app.post(“/signup”, function(request, respond){
const newUser = new User({
username: request.body.username,
password: md5(request.body.password)
});
newUser.save(function(err){
if (err)
console.log(err)
else
respond.sendFile(__dirname + “/public/gallery.html”);
});
});
- After you register with just your username and password (anything can do, it's not that serious. I just wanted to make a private-access project), you can log in and view the gallery. Of course, there's nothing to see there since you didn't add anything ><. But below are the pages that you should see.
- PS. I hope the image markdown works.
> 
> 
* well would you look at that! It works!!
#### login
- `login.html` is the landing page. If you have your toy name and password in the database, you should be able to access `gallery.html`. The callback checks for the correct username and password in the database.
- Remember, when you run the `md5` hashing function on the same string, the hash that is created will always be the same. This is what we look for in the callback. The user input from the html body is hashed and compared to the hash in the database. If they're the same, we have a successful login. If they're not, well, then _something mighty spooky going on._
app.post(“/“, function(request, respond){
const username = request.body.username;
const password = md5(request.body.password);
User.findOne({username: username}, function(error, foundUser){
if (error)
console.log(error);
else {
if (foundUser){
if (foundUser.password === password)
respond.sendFile(__dirname + "/public/gallery.html");
else
respond.send("I feel a great disturbance in the force");
}
}
});
});
```
ejs
because it makes code look hideous.