Samiul Lesum
Samiul Lesum

Reputation: 268

Upload an image to MongoDB using Nodejs, Express, Mongoose and React

I'm working on a simple web app to practice my newly developed skills in web development. I'm trying to upload some information on a book with its' image to MongoDB using Nodejs, Express, Mongoose and React. So far, I was able to upload all the info to MongoDB by clicking a submit button. But whenever I'm trying to add an image to the mongoose schema, post request is not working. I couldn't figure out the problem with my code. Here is the code for Book model:

const mongoose = require("mongoose");

const BookSchema = new mongoose.Schema({
  image: {
    data: Buffer,
    contentType: String
  },
  title: {
    type: String,
    required: true
  },
  isbn: {
    type: String,
    required: true
  },
  author: {
    type: String,
    required: true
  },
  description: {
    type: String
  },
  published_date: {
    type: Date
  },
  publisher: {
    type: String
  },
  updated_date: {
    type: Date,
    default: Date.now
  }
});

module.exports = Book = mongoose.model("book", BookSchema);

Here is the code for post request:

router.post("/", (req, res) => {
  var title= req.body.title;
  var isbn = req.body.isbn;
  var author = req.body.author;
  var description = req.body.description;
  var published_date= req.body.published_date;
  var publisher = req.body.publisher;
  var updated_date = req.body.updated_date;

  var imgPath = req.file.path;
  var image = Book.image.data = fs.readFileSync(imgPath);
  Book.image.contentType = 'image/jpg';

  var newBook = {image: image, title: title, isbn: isbn, author: author, description: description, 
  published_date: published_date, publisher: publisher, updated_date: updated_date};
  Book.create(newBook, function(err, newlyCreated){
    if (err) {
        console.log(err);
    } else {
        console.log(newlyCreated);
    }
 });

})

Here is the code for the front-end using React:

import React, { Component } from "react";
import { Link } from "react-router-dom";
import "../App.css";
import axios from "axios";

class CreateBook extends Component {
  constructor() {
    super();
    this.state = {
      image: "",
      title: "",
      isbn: "",
      author: "",
      description: "",
      published_date: "",
      publisher: ""
    };
    this.onFileChange = this.onFileChange.bind(this);
    this.onSubmit = this.onSubmit.bind(this);
  }

  onChange = e => {
    this.setState({ [e.target.name]: e.target.value });
  };

  onFileChange = e => {
    this.setState({ [e.target.name]: e.target.files[0] })
  }

  onSubmit = e => {
    e.preventDefault();
    const formdata = new FormData()

    formdata.append('image', this.state.image)
    formdata.append('title', this.state.title);
    formdata.append('isbn', this.state.isbn,);
    formdata.append('author', this.state.author);
    formdata.append('description', this.state.description);
    formdata.append('published_date', this.state.published_date);
    formdata.append('publisher', this.state.publisher);


    axios
      .post("http://localhost:8082/api/books", formdata)
      .then(res => {
        console.log(res);
        this.setState({
          image: "",
          title: "",
          isbn: "",
          author: "",
          description: "",
          published_date: "",
          publisher: ""
        });
        this.props.history.push("/");
      })
      .catch(err => {
        console.log("Error in CreateBook!");
      });
  };

  render() {
    return (
      <div className="CreateBook">
        <div className="container">
          <div className="row">
            <div className="col-md-8 m-auto">
              <br />
              <Link to="/" className="btn btn-outline-warning float-left">
                Show BooK List
              </Link>
            </div>
            <div className="col-md-8 m-auto">
              <h1 className="display-4 text-center">Add Book</h1>
              <p className="lead text-center">Create new book</p>

              <form noValidate onSubmit={this.onSubmit}>
                <div className="form-group">
                  <input
                    type="file"
                    placeholder="Browse Image"
                    name="image"
                    className="form-control"

                    onChange={this.onFileChange}
                  />
                </div>
                <button type="button" className="btn btn-primary mb-3">
                  Upload
                </button>
                <br />
                <div className="form-group">
                  <input
                    type="text"
                    placeholder="Title of the Book"
                    name="title"
                    className="form-control"
                    value={this.state.title}
                    onChange={this.onChange}
                  />
                </div>
                <br />

                <div className="form-group">
                  <input
                    type="text"
                    placeholder="ISBN"
                    name="isbn"
                    className="form-control"
                    value={this.state.isbn}
                    onChange={this.onChange}
                  />
                </div>

                <div className="form-group">
                  <input
                    type="text"
                    placeholder="Author"
                    name="author"
                    className="form-control"
                    value={this.state.author}
                    onChange={this.onChange}
                  />
                </div>

                <div className="form-group">
                  <input
                    type="text"
                    placeholder="Describe this book"
                    name="description"
                    className="form-control"
                    value={this.state.description}
                    onChange={this.onChange}
                  />
                </div>

                <div className="form-group">
                  <input
                    type="date"
                    placeholder="published_date"
                    name="published_date"
                    className="form-control"
                    value={this.state.published_date}
                    onChange={this.onChange}
                  />
                </div>
                <div className="form-group">
                  <input
                    type="text"
                    placeholder="Publisher of this Book"
                    name="publisher"
                    className="form-control"
                    value={this.state.publisher}
                    onChange={this.onChange}
                  />
                </div>

                <input
                  type="submit"
                  className="btn btn-outline-warning btn-block mt-4"
                />
              </form>
            </div>
          </div>
        </div>
      </div>
    );
  }
}

export default CreateBook;

I'll highly appreciate any suggestions. Thanks in advance.

Upvotes: 2

Views: 5630

Answers (1)

SARAN SURYA
SARAN SURYA

Reputation: 554

If you are using images of format 'jpeg / png' and if they are less than 16mb, you can go with this github repo, its a module that helps saving images to mongodb easily, and without the complexity of GRIDFS, but in case if your files are greater than 16mb, you need to use GRIDFS,

This is the link for the github repo for images less than 16 mb (and also works well with react)

https://github.com/saran-surya/Mongo-Image-Converter

Hope this helps :)

Upvotes: 2

Related Questions